首页 > 代码库 > BZOJ4238电压

BZOJ4238电压

Description

你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)”。这里简称为JOI社。
JOI社的某个实验室中有着复杂的电路。电路由n个节点和m根细长的电阻组成。节点被标号为1~N
每个节点有一个可设定的状态【高电压】或者【低电压】。每个电阻连接两个节点,只有一端是高电压,另一端是低电压的电阻才会有电流流过。两端都是高电压或者低电压的电阻不会有电流流过。
某天,JOI社为了维护电路,选择了一根电阻,为了能让【只有这根电阻上的电流停止流动,其他M-1根电阻中都有电流流过】,需要调节各节点的电压。为了满足这个条件,能选择的电阻共有多少根?
对了,JOI社这个奇妙的电路是用在什么样的发明上的呢?这是公司内的最高机密,除了社长以外谁都不知道哦~
现在给出电路的信息,请你输出电路维护时可以选择使其不流的电阻的个数。

Input

第一行两个空格分隔的正整数N和M,表示电路中有N个节点和M根电阻。
接下来M行,第i行有两个空格分隔的正整数Ai和Bi(1<=Ai<=N,1<=Bi<=N,Ai≠Bi),表示第i个电阻连接节点Ai和节点Bi。

Output

输出一行一个整数,代表电路维护时可选择的使其不流的电阻个数。

Sample Input

4 4
1 2
2 3
3 2
4 3

Sample Output

2

HINT

可以选择第一根电阻或第四根电阻。

 技术分享
2<=N<=10^5
1<=M<=2*10^5
不保证图是连通的,不保证没有重边
 
题解:
题意即将一张图去掉一条边后,使之是二分图,且该边连接的两个节点可以是同种颜色的。
根据边建出DFS树,则剩余的边都是返祖边,会构成环。
若返祖边连接的两个点dep差为偶数,则该环为奇环,必须在其中去掉一条边;若差为奇数,则该环为偶环,不能再其中去掉一条边。
所以通过返祖边求出所有的环,被所有奇环覆盖且不被偶环覆盖的树边可以取。特别的,若只有一个奇环,则该返祖边可以取。
通过DFS,用类似与差分的方式求出每条边被几个奇环、几个偶环覆盖,最后枚举边,统计答案。
 
代码:
技术分享
 1 var
 2   dep,fa,v,c,good,bad:array[0..500005]of longint;
 3   i,j,k,l,n,m,m1,m2,ans:longint;
 4   b:array[0..1000005,1..2]of longint;
 5 procedure ss(x,pre:longint);
 6 var i:longint;
 7 begin
 8   dep[x]:=dep[fa[x]]+1; v[x]:=1;
 9   i:=c[x];
10   while i>0 do
11   begin
12     if i xor 1=pre then begin i:=b[i,2]; continue; end;
13     if v[b[i,1]]=0 then
14     begin
15       fa[b[i,1]]:=x; ss(b[i,1],i);
16       good[x]:=good[x]+good[b[i,1]];
17       bad[x]:=bad[x]+bad[b[i,1]];
18     end else
19     begin
20       if dep[b[i,1]]>dep[x] then begin i:=b[i,2]; continue; end;
21       if (dep[x]-dep[b[i,1]])mod 2=1 then
22       begin inc(good[x]); dec(good[b[i,1]]); inc(m1); end
23       else begin inc(bad[x]); dec(bad[b[i,1]]); inc(m2); end;
24     end;
25     i:=b[i,2];
26   end;
27 end;
28 begin
29   readln(n,m);
30   for i:=1 to m do
31   begin
32     readln(j,k);
33     b[i*2,1]:=k; b[i*2,2]:=c[j]; c[j]:=i*2;
34     b[i*2+1,1]:=j; b[i*2+1,2]:=c[k]; c[k]:=i*2+1;
35   end;
36   for i:=1 to n do if v[i]=0 then ss(i,0);
37   if m2=1 then inc(ans);
38   for i:=1 to n do if(fa[i]>0)and(bad[i]=m2)and(good[i]=0)then inc(ans);
39   writeln(ans);
40 end.
View Code

BZOJ4238电压