这两题都是强连通。。

上午刚开过,下午放学后就趁热打铁,把这两道题也给解决了。。。

只要把kosaraju的意思理解了,用起来会很顺手的,,对于这一类的题目只需要稍微改下就可以了。。

对于1269题,很明显强连通,,只需要判断Bcnt就行了,判断有多少了强连通分支。。。

1827题,Wiskey只需要和 入度为0的强连通分支打电话。。。

对于这样的强连通分支找到打电话所耗的费用最少的一个,,可以在第二个dfs里面处理一下就行了,记录耗用电话费最少的。。。

1269题就不贴代码了,,

1827代码:

View Code
 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:

View Code
 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 }
posted on 2011-04-19 17:14  奋斗青春  阅读(771)  评论(0编辑  收藏  举报