强连通 HDU 1827
n个点m条边
n个权lcy 要叫这个人的花费
m条边
缩点后 新的图中 入度为0的点要通知 通知强连通分量中权值最小的
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<queue> 5 #include<math.h> 6 #include<stack> 7 8 using namespace std; 9 10 #define MAXN 100010 11 #define inf 100000000 12 int head[MAXN],low[MAXN],dfn[MAXN],f[MAXN],in[MAXN],out[MAXN],z[MAXN]; 13 bool vis[MAXN]; 14 int cnt,k,num; 15 struct edg 16 { 17 int fr,to,next; 18 19 }x[MAXN]; 20 21 void add(int u,int v) 22 { 23 x[cnt].next=head[u]; 24 x[cnt].fr=u; 25 x[cnt].to=v; 26 head[u]=cnt++; 27 } 28 stack<int>s; 29 30 void dfs(int u) 31 { 32 low[u]=dfn[u]=k++; 33 vis[u]=1; 34 s.push(u); 35 int i; 36 for(i=head[u];i!=-1;i=x[i].next) 37 { 38 int t=x[i].to; 39 if(!dfn[t]) 40 { 41 dfs(t); 42 low[u]=min(low[u],low[t]); 43 } 44 else if(vis[t]) 45 low[u]=min(low[u],dfn[t]); 46 } 47 if(low[u]==dfn[u]) 48 { 49 num++; 50 while(!s.empty()) 51 { 52 int now=s.top(); 53 s.pop(); 54 vis[now]=0; 55 f[now]=num; 56 if(now==u)break; 57 } 58 } 59 } 60 61 int main() 62 { 63 int n,m,t; 64 65 while(scanf("%d%d",&n,&m)!=EOF) 66 { 67 int i,j; 68 for(i=1;i<=n;i++) 69 scanf("%d",&z[i]); 70 memset(head,-1,sizeof(head)); 71 cnt=0; 72 for(i=1;i<=m;i++) 73 { 74 int a,b; 75 scanf("%d%d",&a,&b); 76 add(a,b); 77 } 78 k=1; 79 num=0; 80 memset(dfn,0,sizeof(dfn)); 81 memset(low,0,sizeof(low)); 82 memset(vis,0,sizeof(vis)); 83 memset(f,0,sizeof(f)); 84 for(i=1;i<=n;i++) 85 { 86 if(!dfn[i]) 87 dfs(i); 88 } 89 memset(head,-1,sizeof(head)); 90 int en=cnt; 91 memset(in,0,sizeof(in)); 92 93 for(i=0;i<en;i++) 94 { 95 int u,v; 96 u=f[x[i].fr]; 97 v=f[x[i].to]; 98 if(u!=v) 99 { 100 add(u,v); 101 in[v]++; 102 } 103 } 104 int ans=0,ans1=0; 105 106 for(i=1;i<=num;i++) 107 { 108 if(in[i]==0) 109 { 110 ans1++; 111 int m1=inf; 112 for(j=1;j<=n;j++) 113 { 114 if(f[j]==i) 115 m1=min(m1,z[j]); 116 } 117 ans=ans+m1; 118 } 119 } 120 printf("%d %d\n",ans1,ans); 121 } 122 return 0; 123 }
ans+=w, num++
posted on 2016-11-13 16:08 HelloWorld!--By-MJY 阅读(135) 评论(0) 编辑 收藏 举报