标签:intelligence system hdu 3072 强联通缩点 贪心
3 3 0 1 100 1 2 50 0 2 100 3 3 0 1 100 1 2 50 2 1 100 2 2 0 1 50 0 1 100
150 100 50
题意:n个人m个单向关系,现在要通知所有的人,两个人之间联系有费用,求最小费用,处于同一个联通块的两个人之间通讯不需要花费。
思路:先建图使用Tarjan算法缩点,然后根据题意我们应该求缩点后新图的最小树形图,但是这里没必要,为什么?仔细想一想,首先题意说总是有解,所以最小树形图一定存在,那么我们对于每一个点在它的所有入边中选择一个花费最小的入边(入度为零的点除外)那么答案就是每个点的最小花费之和。这样贪心是可行的,因为在这个过程中不会出现环,很容易想到,如果出现了环那么这个环就又是一个联通块了,可是我们之前已经求出了联通块,保证了新图中没有环。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; const int MAXN = 50010;//点数 const int MAXM = 500010;//边数 struct Edge { int to,c,next; }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc int Index,top; int scc;//强联通分量的个数 bool Instack[MAXN]; int num[MAXN];//各个强联通分量包含的点的个数,数组编号为1~scc //num数组不一定需要,结合实际情况 void addedge(int u,int v,int c) { edge[tot].to=v; edge[tot].c=c; edge[tot].next=head[u]; head[u]=tot++; } void Tarjan(int u) { int v; Low[u]=DFN[u]=++Index; Stack[top++]=u; Instack[u]=true; for (int i=head[u];i+1;i=edge[i].next) { v=edge[i].to; if (!DFN[v]) { Tarjan(v); if (Low[u]>Low[v]) Low[u]=Low[v]; } else if (Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v]; } if (Low[u]==DFN[u]) { scc++; do{ v=Stack[--top]; Instack[v]=false; Belong[v]=scc; num[scc]++; }while (v!=u); } } void solve(int N) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(num,0,sizeof(num)); Index=scc=top=0; for (int i=1;i<=N;i++) //点的编号从1开始 if (!DFN[i]) Tarjan(i); } int n,m; int d[MAXN],in[MAXN]; void init() { tot=0; memset(head,-1,sizeof(head)); memset(d,INF,sizeof(d)); memset(in,0,sizeof(in)); } int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin); #endif int i,j,u,v,c; while (~sff(n,m)) { init(); for (i=0;i<m;i++) { sfff(u,v,c); u++;v++; addedge(u,v,c); } solve(n); int ans=0; for (u=1;u<=n;u++) { for (i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if (Belong[u]!=Belong[v]) in[Belong[v]]++; } } for (u=1;u<=n;u++) { for (j=head[u];~j;j=edge[j].next) { int v=edge[j].to; if (Belong[u]!=Belong[v]) d[Belong[v]]=min(d[Belong[v]],edge[j].c); } } for (i=1;i<=scc;i++) { if (in[i]==0) continue; ans+=d[i]; } pf("%d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
Intelligence System (hdu 3072 强联通缩点+贪心)
标签:intelligence system hdu 3072 强联通缩点 贪心
原文地址:http://blog.csdn.net/u014422052/article/details/46849673