刚开始没看明白题意,以为只是强联通,题上的测试实例都没能看明白!!
后来看明白了,不过没想到强联通缩点之后用什么方法求,也有想到过二分匹配,不过没怎么想就把它给排除了,50000个点啊,二分匹配能受的了吗!!
同学做出来后告诉我们是二分匹配,当时第一反应就是这题数据相当弱!!!
后来敲了下代码,发现如果数据不是很强的话,二分匹配果然可行,最后等于求最小路径覆盖=(顶点数 - 最大匹配数);
题目上说的很清楚,What’s more, for each pair of city (u, v), if there is one way to go from u to v and go from v to u, (u, v) have to belong to a same state
,所以显然要先缩点,之后用二分匹配求最小路径覆盖,思路很清晰!
代码:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 # include<stdio.h>
2 # include<string.h>
3 # define N 50005
4 # define M 100005
5 struct node{
6 int from,to,next;
7 }edge1[M],edge2[M],edge[M];
8 int tol1,tol2,head1[N],head2[N],T[N],Bcnt,Tcnt,n,m,visit1[N],visit2[N],Belong[N],head[N],visit[N],tol,use[N];
9 void add(int a,int b)
10 {
11 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
12 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
13 }
14 void add1(int a,int b)
15 {
16 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
17 }
18 void dfs1(int i)
19 {
20 int j,index;
21 visit1[i]=1;
22 for(j=head1[i];j!=-1;j=edge1[j].next)
23 {
24 index=edge1[j].to;
25 if(!visit1[index]) dfs1(index);
26 }
27 T[Tcnt++]=i;
28 }
29 void dfs2(int i)
30 {
31 int j,index;
32 Belong[i]=Bcnt;
33 visit2[i]=1;
34 for(j=head2[i];j!=-1;j=edge2[j].next)
35 {
36 index=edge2[j].to;
37 if(!visit2[index]) dfs2(index);
38 }
39 }
40 int getnum(int i)
41 {
42 int j,index;
43 for(j=head[i];j!=-1;j=edge[j].next)
44 {
45 index=edge[j].to;
46 if(visit[index]==0)
47 {
48 visit[index]=1;
49 if(use[index]==-1 || getnum(use[index])==1)
50 {
51 use[index]=i;
52 return 1;
53 }
54 }
55 }
56 return 0;
57 }
58 int main()
59 {
60 int ncase,i,a,b,count;
61 scanf("%d",&ncase);
62 while(ncase--)
63 {
64 scanf("%d%d",&n,&m);
65 tol1=tol2=0;
66 Tcnt=Bcnt=0;
67 memset(head1,-1,sizeof(head1));
68 memset(head2,-1,sizeof(head2));
69 for(i=1;i<=m;i++)
70 {
71 scanf("%d%d",&a,&b);
72 add(a,b);
73 }
74 memset(visit1,0,sizeof(visit1));
75 memset(visit2,0,sizeof(visit2));
76 for(i=1;i<=n;i++)
77 if(visit1[i]==0) dfs1(i);
78 for(i=Tcnt-1;i>=0;i--)
79 {
80 if(visit2[T[i]]==0)
81 {
82 dfs2(T[i]);
83 Bcnt++;
84 }
85 }
86 tol=0;
87 memset(head,-1,sizeof(head));
88 for(i=0;i<tol1;i++)
89 {
90 a=Belong[edge1[i].from];
91 b=Belong[edge1[i].to];
92 if(a!=b) add1(a,b);
93 }
94 memset(use,-1,sizeof(use));
95 count=0;
96 for(i=0;i<Bcnt;i++)
97 {
98 memset(visit,0,sizeof(visit));
99 if(getnum(i)==1) count++;
100 }
101 printf("%d\n",Bcnt-count);
102 }
103 return 0;
104 }