标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1904 Accepted Submission(s): 824
题意:有N个人编号从0到N-1,给出M组关系<u,v,w>表示u联系v需要费用w(但不代表v联系u需要费用w)。若一个集合中 任意两个人可以互相联系(不管是直接联系的还是通过其他人间接联系的),那么在这个集合里面联系的费用可以忽略。现在你是编号0,问你联系到所有人的最小费用。题目保证至少有一组方案使得你可以联系到所有人。
题解:求出所有的scc,因为同一个scc中的人相互通知不需要花费,所以总花费是连接所有scc的花费
在缩点的过程同时更新连接scc所需要的最小花费 最后累加即可
#include<stdio.h> #include<string.h> #include<stack> #include<algorithm> #define MAX 100010 #define INF 0x3f3f3f #include<vector> using namespace std; int n,m; int head[MAX],ans; int low[MAX],dfn[MAX]; int sccno[MAX]; int scccnt,dfsclock; vector<int>scc[MAX]; vector<int>newmap[MAX]; stack<int>s; int instack[MAX],money[MAX]; struct node { int beg,end,next; int cost; }edge[MAX]; void init() { ans=0; memset(head,-1,sizeof(head)); } void add(int beg,int end,int cost) { edge[ans].beg=beg; edge[ans].end=end; edge[ans].cost=cost; edge[ans].next=head[beg]; head[beg]=ans++; } void getmap() { int a,b,c,i; while(m--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); } } void tarjan(int u) { int i,v; s.push(u); instack[u]=1; low[u]=dfn[u]=++dfsclock; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].end; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { scccnt++; while(1) { v=s.top(); s.pop(); instack[v]=0; sccno[v]=scccnt; if(v==u) break; } } } void find(int l,int r) { memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); memset(sccno,0,sizeof(sccno)); dfsclock=scccnt=0; for(int i=l;i<=r;i++) { if(!dfn[i]) tarjan(i); } } void suodian() { int i; for(i=1;i<=scccnt;i++) { newmap[i].clear(); money[i]=INF; } for(i=0;i<ans;i++) { int u=sccno[edge[i].beg]; int v=sccno[edge[i].end]; if(u!=v)//u不等于v证明u和v不在同一个scc,则u-->v这条边是连接两个scc的边, { //拿这条边和其他的可以连接这两个scc的边比较取最小值 newmap[u].push_back(v); money[v]=min(edge[i].cost,money[v]); } } } void solve() { int i,j; int sum=0; for(i=1;i<=scccnt;i++) { if(sccno[0]!=i)//0所在的scc不需要花费,因为消息就是从这里来的 sum+=money[i]; } printf("%d\n",sum); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); getmap(); find(0,n-1); suodian(); solve(); } return 0; }
hdoj 3072 Intelligence System【求scc&&缩点】【求连通所有scc的最小花费】
标签:
原文地址:http://www.cnblogs.com/tonghao/p/4819136.html