这两题都是强连通。。
上午刚开过,下午放学后就趁热打铁,把这两道题也给解决了。。。
只要把kosaraju的意思理解了,用起来会很顺手的,,对于这一类的题目只需要稍微改下就可以了。。
对于1269题,很明显强连通,,只需要判断Bcnt就行了,判断有多少了强连通分支。。。
1827题,Wiskey只需要和 入度为0的强连通分支打电话。。。
对于这样的强连通分支找到打电话所耗的费用最少的一个,,可以在第二个dfs里面处理一下就行了,记录耗用电话费最少的。。。
1269题就不贴代码了,,
1827代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # include<stdio.h> 2 # include<string.h> 3 # define N 1005 4 # define M 2005 5 struct node{ 6 int from,to,next; 7 }edge1[M],edge2[M]; 8 int visit1[N],visit2[N],head1[N],head2[N],T[N]; 9 int in_degree[N],out_degree[N],tol1,tol2,Bcnt,Tcnt; 10 int val[N],v1[N],min,Belong[N]; 11 void add(int a,int b) 12 { 13 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++; 14 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++; 15 } 16 void dfs1(int x) 17 { 18 int i; 19 visit1[x]=1; 20 for(i=head1[x];i!=-1;i=edge1[i].next) 21 if(visit1[edge1[i].to]==0) dfs1(edge1[i].to); 22 T[Tcnt++]=x; 23 } 24 void dfs2(int x) 25 { 26 int i; 27 Belong[x]=Bcnt; 28 if(val[x]<min) min=val[x]; 29 visit2[x]=1; 30 for(i=head2[x];i!=-1;i=edge2[i].next) 31 if(visit2[edge2[i].to]==0) dfs2(edge2[i].to); 32 } 33 int main() 34 { 35 int i,n,m,sum,x,y,a,b,count; 36 while(scanf("%d%d",&n,&m)!=EOF) 37 { 38 tol1=tol2=0; 39 Bcnt=Tcnt=0; 40 for(i=1;i<=n;i++) 41 { 42 head1[i]=-1; 43 head2[i]=-1; 44 visit1[i]=0; 45 visit2[i]=0; 46 scanf("%d",&val[i]); 47 } 48 while(m--) 49 { 50 scanf("%d%d",&a,&b); 51 add(a,b); 52 } 53 for(i=1;i<=n;i++) 54 if(visit1[i]==0) dfs1(i); 55 for(i=Tcnt-1;i>=0;i--) 56 { 57 if(visit2[T[i]]==0) 58 { 59 min=0xfffffff; 60 dfs2(T[i]); 61 v1[Bcnt]=min; 62 Bcnt++; 63 } 64 } 65 for(i=0;i<Bcnt;i++) 66 { 67 in_degree[i]=0; 68 out_degree[i]=0; 69 } 70 for(i=0;i<tol1;i++) 71 { 72 x=Belong[edge1[i].from]; 73 y=Belong[edge1[i].to]; 74 if(x!=y) 75 { 76 in_degree[y]=1; 77 out_degree[x]=1; 78 } 79 } 80 sum=0; 81 count=0; 82 for(i=0;i<Bcnt;i++) 83 { 84 if(in_degree[i]==0) {sum+=v1[i];count++;} 85 } 86 printf("%d %d\n",count,sum); 87 } 88 return 0; 89 }
顺便再贴一个刚 学的tarjan的模版,代码很丑陋!!
1827:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # include<stdio.h>
2 # include<string.h>
3 # include<stack>
4 usingnamespace std;
5 # define N 1005
6 # define M 2005
7 struct node{
8 int from,to,next;
9 }edge[M];
10 int head[N],tol,vis[N],n,m,cnt,visit[N],dfn[N],low[N],count,Belong[N],sum,val[N],val1[N],count1,degree[N];
11 stack<int>Stack;
12 void add(int a,int b)
13 {
14 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
15 }
16 int min(int a,int b)
17 {
18 return a<b?a:b;
19 }
20 void tarjan(int u)
21 {
22 int j,v,Min;
23 dfn[u]=low[u]=cnt++;
24 Stack.push(u);
25 visit[u]=vis[u]=1;
26 for(j=head[u];j!=-1;j=edge[j].next)
27 {
28 v=edge[j].to;
29 if(!visit[v])//
30 {
31 tarjan(v);
32 low[u]=min(low[v],low[u]);
33 }
34 elseif(vis[v])//
35 low[u]=min(low[u],dfn[v]);
36 }
37 if(dfn[u]==low[u])
38 {
39 count++;
40 Min=val[u];
41 do{
42 v=Stack.top();
43 Stack.pop();
44 vis[v]=0;
45 Min=min(Min,val[v]);
46 Belong[v]=count;
47 }while(v!=u);
48 val1[count]=Min;
49 }
50 }
51 int main()
52 {
53 int i,a,b,j,u;
54 while(scanf("%d%d",&n,&m)!=EOF)
55 {
56 //if(n==0 && m==0) break;
57 for(i=1;i<=n;i++)
58 scanf("%d",&val[i]);
59 memset(head,-1,sizeof(head));
60 tol=0;
61 cnt=0;
62 for(i=1;i<=m;i++)
63 {
64 scanf("%d%d",&a,&b);
65 add(a,b);
66 }
67 memset(vis,0,sizeof(vis));
68 memset(visit,0,sizeof(visit));
69 sum=0;//表示需要的最少话费
70 count=0;//表示强联通分量的个数
71 for(i=1;i<=n;i++)
72 if(!visit[i]) tarjan(i);
73 //if(count==1) printf("Yes\n");
74 //else printf("No\n");
75 memset(degree,0,sizeof(degree));
76 for(i=1;i<=n;i++)
77 {
78 for(j=head[i];j!=-1;j=edge[j].next)
79 {
80 u=edge[j].to;
81 if(Belong[i]==Belong[u]) continue;
82 degree[Belong[u]]++;
83 }
84 }
85 count1=0;
86 for(i=1;i<=count;i++)
87 {
88 if(!degree[i]) {sum+=val1[i];count1++;}
89 }
90 //for(i=1;i<=n;i++)
91 //printf("%d:%d\n",i,Belong[i]);
92 printf("%d %d\n",count1,sum);
93 }
94 return0;
95 }