【问题描述】
“这一切都是命运石之门的选择。”
试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短信,并由此得知了伦太郎制作出了电话微波炉(仮)。
为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯网络,传达到所有分部。
SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线路有一个固定的通讯花费Ci
为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向另一个与它有线路的部门传递(可能存在多条通信线路)。我们定义总费用为所有部门传递消息的费用和
幸运的是,如果两个部门可以直接或间接地相互传递消息(即能按照上述方法将信息由X传递到Y,同时能由Y传递到X),我们就可以忽略它们之间的花费。
由于资金问题(预算都花在粒子对撞机上了),SERN总部的工程师希望知道达到目标的最小花费是多少。
【输入格式】
多组数据,文件以2个0结尾。
每组数据第一行,一个整数N,表示有N个包括总部的部门(从0开始编号)。然后是一个整数M,表示有M条单向通讯线路。
接下来M行,每行三个整数,Xi,Yi,Ci,表示第i条线路从Xi连向Yi,花费Ci。
【输出格式】
每组数据一行,一个整数表示达到目标的最小花费
题目中说道可以相互到达的点不计入花费,即环上的点不考虑,所以缩点。
然后就直接有向图上dp求路线最小值之和。
似乎写了拓扑就不需要递归了?
#include
#include
#include
#include
#include
#include
#define db double
#define sg string
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x))
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
#define res(i,x) for(ll i=head[x];i;i=nxt[i])
using namespace std;
const ll N=5e4+5;
const ll M=1e5+5;
const ll Inf=1e18;
const ll Mod=1e9+7;
const db Eps=1e-10;
ll top,scc,tim,dis[N],vis[N],size[N],stack[N];
ll n,m,f[N],dfn[N],low[N],bel[N];
struct nnode {
ll num,dis;
bool operator < (const nnode &a) const {
return a.dis'9'||ch<'0'){if(ch=='-')f=1;ch=getchar;}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar;}
return f?-x:x;
}
void init() {
G1.init(),G2.init();
scc=top=tim=0;
mem(bel,0);mem(dfn,0);
mem(low,0);mem(vis,0);mem(stack,0);
}
void File() {
freopen("message.in","r",stdin);
freopen("message.out","w",stdout);
}
int main() {
// File();
while(true) {
n=read(),m=read();
if(n==0&&m==0) return 0;
init();
rep(i,1,m) {
ll x=read()+1,y=read()+1,z=read();G1.ins(x,y,z);
}
rep(i,1,n) if(!dfn[i]) G1.tarjan(i);
rep(i,1,n) for(ll j=G1.head[i];j;j=G1.nxt[j]) {
ll y=G1.to[j],z=G1.edge[j];
if(bel[i]!=bel[y]) G2.ins(bel[i],bel[y],z);
}
rep(i,1,scc) f[i]=Inf;f[bel[1]]=0;
G2.dp(bel[1]);
ll ans=0;
rep(i,1,scc) ans+=f[i];
printf("%lld\n",ans);
}
return 0;
}