1093: [ZJOI2007]最大半连通子图
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1530 Solved: 589
[Submit][Status]
Description
Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述。接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
Sample Input
6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
3
3
HINT
对于20%的数据, N ≤18;对于60%的数据, N ≤10000;对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。
Source
题解:
按输入构图,tarjan缩点之后变为DAG,最大节点数即为“最长链”,一条链的长度定义为所有节点的权值之和,每个scc的权值为它的节点个数
最长链的求法类似于拓扑排序+DP
求构成方案只要在取max的时候判断一下即可,利用加法原理
答案扫一遍即可(ms也可以加一个虚拟节点,由所有scc向它连边,然后最后直接输出该点的信息就行。。。)
本题还有一个注意的地方就是tarjan之后重构图的时候会加入重边,要消除重边的影响可以在topsort的时候对访问过的节点做一下标记
具体实现见代码
代码:
1.
1 const maxn=110000+1000;maxm=1100000+1000; 2 type node=record 3 from,go,next:longint; 4 end; 5 var e:array[0..maxm] of node; 6 e2:array[0..maxm] of node; 7 a,b:array[0..maxm] of longint; 8 n,m,h,t,x,y,i,ti,top,cnt,ans1,ans2,tot,p:longint; 9 q,head,head2,dfn,low,sta,scc,s,v,num,inp,vis:array[0..maxn] of longint; 10 function min(x,y:longint):longint; 11 begin 12 if x<y then exit(x) else exit(y); 13 end; 14 15 procedure insert(x,y:longint); 16 begin 17 inc(tot); 18 e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot; 19 end; 20 procedure insert2(x,y:longint); 21 begin 22 inc(tot); 23 e2[tot].go:=y;e2[tot].next:=head2[x];head2[x]:=tot; 24 end; 25 procedure dfs(x:longint); 26 var i,y,z:longint; 27 begin 28 inc(ti);dfn[x]:=ti;low[x]:=ti;inc(top);sta[top]:=x; 29 i:=head[x]; 30 while i<>0 do 31 begin 32 y:=e[i].go; 33 if dfn[y]=0 then 34 begin 35 dfs(y); 36 low[x]:=min(low[x],low[y]); 37 end 38 else if scc[y]=0 then low[x]:=min(low[x],dfn[y]); 39 i:=e[i].next; 40 end; 41 if low[x]=dfn[x] then 42 begin 43 inc(cnt); 44 while true do 45 begin 46 z:=sta[top];dec(top); 47 scc[z]:=cnt;inc(s[cnt]); 48 if z=x then break; 49 end; 50 end; 51 end; 52 procedure tarjan; 53 begin 54 ti:=0;cnt:=0;ti:=0; 55 fillchar(dfn,sizeof(dfn),0); 56 for i:=1 to n do if dfn[i]=0 then dfs(i); 57 end; 58 procedure init; 59 begin 60 readln(n,m,p); 61 for i:=1 to m do 62 begin 63 readln(a[i],b[i]); 64 insert(a[i],b[i]); 65 end; 66 end; 67 procedure main; 68 begin 69 tarjan; 70 fillchar(inp,sizeof(inp),0);tot:=0; 71 for i:=1 to m do 72 begin 73 x:=scc[a[i]];y:=scc[b[i]]; 74 if x<>y then begin inc(inp[y]);insert2(x,y);end; 75 end; 76 h:=0;t:=0; 77 for i:=1 to cnt do 78 if inp[i]=0 then begin inc(t);q[t]:=i;v[i]:=s[i];num[i]:=1;end; 79 while h<t do 80 begin 81 inc(h);x:=q[h]; 82 i:=head2[x]; 83 while i<>0 do 84 begin 85 y:=e2[i].go; 86 if vis[y]<>x then 87 begin 88 vis[y]:=x; 89 if v[x]+s[y]>v[y] then begin v[y]:=v[x]+s[y];num[y]:=num[x];end 90 else if v[x]+s[y]=v[y] then num[y]:=(num[y]+num[x]) mod p; 91 end; 92 dec(inp[y]);if inp[y]=0 then begin inc(t);q[t]:=y;end; 93 i:=e2[i].next; 94 end; 95 end; 96 ans1:=0;ans2:=0; 97 for i:=1 to cnt do if v[i]>ans1 then begin ans1:=v[i];ans2:=num[i];end 98 else if v[i]=ans1 then ans2:=(ans2+num[i]) mod p; 99 writeln(ans1); 100 writeln(ans2); 101 end; 102 begin 103 assign(input,'input.txt');assign(output,'output.txt'); 104 reset(input);rewrite(output); 105 init; 106 main; 107 close(input);close(output); 108 end.
2.加虚拟节点
1 const maxn=110000+1000;maxm=1100000+1000; 2 type node=record 3 from,go,next:longint; 4 end; 5 var e:array[0..maxm] of node; 6 e2:array[0..2*maxm] of node; 7 a,b:array[0..maxm] of longint; 8 n,m,h,t,x,y,i,ti,top,cnt,ans1,ans2,tot,p:longint; 9 q,head,head2,dfn,low,sta,scc,s,v,num,inp,vis:array[0..maxn] of longint; 10 function min(x,y:longint):longint; 11 begin 12 if x<y then exit(x) else exit(y); 13 end; 14 15 procedure insert(x,y:longint); 16 begin 17 inc(tot); 18 e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot; 19 end; 20 procedure insert2(x,y:longint); 21 begin 22 inc(tot); 23 e2[tot].go:=y;e2[tot].next:=head2[x];head2[x]:=tot; 24 end; 25 procedure dfs(x:longint); 26 var i,y,z:longint; 27 begin 28 inc(ti);dfn[x]:=ti;low[x]:=ti;inc(top);sta[top]:=x; 29 i:=head[x]; 30 while i<>0 do 31 begin 32 y:=e[i].go; 33 if dfn[y]=0 then 34 begin 35 dfs(y); 36 low[x]:=min(low[x],low[y]); 37 end 38 else if scc[y]=0 then low[x]:=min(low[x],dfn[y]); 39 i:=e[i].next; 40 end; 41 if low[x]=dfn[x] then 42 begin 43 inc(cnt); 44 while true do 45 begin 46 z:=sta[top];dec(top); 47 scc[z]:=cnt;inc(s[cnt]); 48 if z=x then break; 49 end; 50 end; 51 end; 52 procedure tarjan; 53 begin 54 ti:=0;cnt:=0;ti:=0; 55 fillchar(dfn,sizeof(dfn),0); 56 for i:=1 to n do if dfn[i]=0 then dfs(i); 57 end; 58 procedure init; 59 begin 60 readln(n,m,p); 61 for i:=1 to m do 62 begin 63 readln(a[i],b[i]); 64 insert(a[i],b[i]); 65 end; 66 end; 67 procedure main; 68 begin 69 tarjan; 70 fillchar(inp,sizeof(inp),0);tot:=0; 71 for i:=1 to m do 72 begin 73 x:=scc[a[i]];y:=scc[b[i]]; 74 if x<>y then begin inc(inp[y]);insert2(x,y);end; 75 end; 76 for i:=1 to cnt do insert2(i,cnt+1); 77 inp[cnt+1]:=cnt;s[cnt+1]:=0; 78 h:=0;t:=0; 79 for i:=1 to cnt do 80 if inp[i]=0 then begin inc(t);q[t]:=i;v[i]:=s[i];num[i]:=1;end; 81 while h<t do 82 begin 83 inc(h);x:=q[h]; 84 i:=head2[x]; 85 while i<>0 do 86 begin 87 y:=e2[i].go; 88 if vis[y]<>x then 89 begin 90 vis[y]:=x; 91 if v[x]+s[y]>v[y] then begin v[y]:=v[x]+s[y];num[y]:=num[x];end 92 else if v[x]+s[y]=v[y] then num[y]:=(num[y]+num[x]) mod p; 93 end; 94 dec(inp[y]);if inp[y]=0 then begin inc(t);q[t]:=y;end; 95 i:=e2[i].next; 96 end; 97 end; 98 writeln(v[cnt+1]); 99 writeln(num[cnt+1]); 100 end; 101 begin 102 assign(input,'input.txt');assign(output,'output.txt'); 103 reset(input);rewrite(output); 104 init; 105 main; 106 close(input);close(output); 107 end.