CH Round #17 舞动的夜晚
舞动的夜晚 CH Round #17
描述
L公司和H公司举办了一次联谊晚会。晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞。在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一共有T对。舞会上,每位员工会尝试选择一名Ta认识的对方公司的员工作为舞伴,并且每位员工至多跳一支舞。完成的交际舞的数量越多,晚会的气氛就越热烈。顾及到晚会的气氛,员工们希望知道,哪些员工之间如果进行了交际舞,就会使整场晚会能够完成的交际舞的最大数量减小。
输入格式
第一行三个整数N、M、T。
接下来T行每行两个整数x、y,表示L公司的员工x和H公司的员工y互相认识。
输出格式
第一行一个整数cnt,表示进行了交际舞后会使整场晚会能够完成的交际舞的最大数量减小的员工有多少对。
第二行cnt个整数,升序输出这样的一对员工的认识关系的编号(他们的认识关系是在输入数据中读入的第几条认识关系)。如果cnt=0,输出一个空行。
样例输入
3 3 6 1 1 2 1 2 2 3 1 3 2 3 3
样例输出
3 2 4 5
数据范围与约定
- 对于50%的数据,1<=N,M<=100,1<=T<=1000。
- 对于100%的数据,1<=N,M<=10000,1<=T<=100000,1<=x<=N,1<=y<=M
题解:
其实我很想问,这范围是给网络流的?忽然想到,白书上有句话---可以证明,对于二分图最大匹配这样的特殊图,dinic算法的复杂度为O(sqrt(n)*m);
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
二分图的可行边/必须边: 先用Dinic求出任意一组最大匹配。 建一张新图:对于匹配边(u,v),v到u连边;非匹配边u到v连边; 对于匹配的左部点u,u到S连边;未匹配的左部点u,S到u连边; 对于匹配的右部点v,T到v连边;未匹配的右部点v,v到T连边。 用Tarjan求强连通分量,若(u,v)是匹配边或者u,v在同一个SCC中——可行边;若(u,v)是匹配边且u,v不在同一个SCC中——必须边。---lyd
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
其实后面的一大坨构图就是一句话---残量网络
直接在残量网络里tarjan,然后扫一遍即可
ps:这题教育我,即使感觉数组不会越界,也一定要把数组开大,不爆内存就好!
代码:
1 const inf=maxlongint; 2 type node=record 3 from,go,next,v:longint; 4 end; 5 var tot,i,j,n,m,maxflow,l,r,s,t,ans,num,cnt,ti,top:longint; 6 h,head,q,cur,a,dfn,low,sta,scc,x,y:array[0..500000] of longint; 7 e:array[0..5000000] of node; 8 b:array[0..500000] of boolean; 9 function min(x,y:longint):longint; 10 begin 11 if x<y then exit(x) else exit(y); 12 end; 13 procedure ins(x,y,z:longint); 14 begin 15 inc(tot); 16 e[tot].from:=x;e[tot].go:=y;e[tot].v:=z;e[tot].next:=head[x];head[x]:=tot; 17 end; 18 procedure insert(x,y,z:longint); 19 begin 20 ins(x,y,z);ins(y,x,0); 21 end; 22 function bfs:boolean; 23 var i,x,y:longint; 24 begin 25 fillchar(h,sizeof(h),0); 26 l:=0;r:=1;q[1]:=s;h[s]:=1; 27 while l<r do 28 begin 29 inc(l); 30 x:=q[l]; 31 i:=head[x]; 32 while i<>0 do 33 begin 34 y:=e[i].go; 35 if (e[i].v<>0) and (h[y]=0) then 36 begin 37 h[y]:=h[x]+1; 38 inc(r);q[r]:=y; 39 end; 40 i:=e[i].next; 41 end; 42 end; 43 exit (h[t]<>0); 44 end; 45 function dfs(x,f:longint):longint; 46 var i,y,used,tmp:longint; 47 begin 48 if x=t then exit(f); 49 used:=0; 50 i:=cur[x]; 51 while i<>0 do 52 begin 53 y:=e[i].go; 54 if (h[y]=h[x]+1) and (e[i].v<>0) then 55 begin 56 tmp:=dfs(y,min(e[i].v,f-used)); 57 dec(e[i].v,tmp);if e[i].v<>0 then cur[x]:=i; 58 inc(e[i xor 1].v,tmp); 59 inc(used,tmp); 60 if used=f then exit(f); 61 end; 62 i:=e[i].next; 63 end; 64 if used=0 then h[x]:=-1; 65 exit(used); 66 end; 67 procedure dinic; 68 begin 69 while bfs do 70 begin 71 for i:=s to t do cur[i]:=head[i]; 72 inc(maxflow,dfs(s,inf)); 73 end; 74 end; 75 procedure dfs(x:longint); 76 var i,y,z:longint; 77 begin 78 inc(ti);dfn[x]:=ti;low[x]:=ti;inc(top);sta[top]:=x; 79 i:=head[x]; 80 while i<>0 do 81 begin 82 y:=e[i].go; 83 if e[i].v<>0 then 84 begin 85 if dfn[y]=0 then 86 begin 87 dfs(y); 88 low[x]:=min(low[x],low[y]); 89 end 90 else if scc[y]=0 then low[x]:=min(low[x],dfn[y]); 91 end; 92 i:=e[i].next; 93 end; 94 if low[x]=dfn[x] then 95 begin 96 inc(cnt); 97 while true do 98 begin 99 z:=sta[top];dec(top); 100 scc[z]:=cnt; 101 if z=x then break; 102 end; 103 end; 104 end; 105 procedure tarjan; 106 begin 107 ti:=0;cnt:=0;ti:=0; 108 fillchar(dfn,sizeof(dfn),0); 109 for i:=s to t do if dfn[i]=0 then dfs(i); 110 end; 111 procedure init; 112 begin 113 tot:=1; 114 readln(n,m,num); 115 s:=0;t:=n+m+1; 116 for i:=1 to n do insert(s,i,1); 117 for i:=1 to num do 118 begin 119 readln(x[i],y[i]);inc(y[i],n); 120 a[i]:=tot+1;insert(x[i],y[i],1); 121 end; 122 for i:=n+1 to n+m do insert(i,t,1); 123 end; 124 procedure main; 125 begin 126 maxflow:=0; 127 dinic; 128 tarjan; 129 ans:=0; 130 for i:=1 to num do 131 begin 132 if (e[a[i]].v<>0) and (scc[x[i]]<>scc[y[i]]) then 133 begin 134 b[i]:=true;inc(ans); 135 end; 136 end; 137 writeln(ans); 138 if ans=0 then writeln else for i:=1 to num do if b[i] then write(i,' '); 139 end; 140 141 begin 142 assign(input,'input.txt');assign(output,'output.txt'); 143 reset(input);rewrite(output); 144 init; 145 main; 146 close(input);close(output); 147 end.