【問題描述】
科學家在“無限神機”(Infinity Machine)找到一個奇怪的機制,這個機制有N 個元件,有M條電線連接這些元件,所有元件都是連通的。兩個元件之間可能有多條 電線連接。 科學家對這些元件可以任意地設置爲“高電壓”和“低電壓”兩種模式,如果一 條電線的一端爲高電壓,另一端爲低電壓,這條電線就會產生電流。 爲了安全的研究“無限神機”,科學家需要找到一條電線,將它的兩端設爲相同 的電壓,並且除選擇的這條電線外,其它所有電線都有電流(否則就沒有研究的價值 了)。 有多少條電線滿足這樣的條件?
【輸入格式】
從文件 voltage.in 中讀入數據。 輸入的第一行包含兩個正整數 n, m ,表示元件數和電線數。 接下來 m 行,每行兩個整數 u, v,表示元件 u 和元件 v 有一條電線連接
【輸出格式】
輸出到文件 voltage.out 中。 輸出一個整數,表示有多少條電線滿足條件。
【樣例1輸入】
4 5 1 2 1 3 1 4 2 4 3 4
【樣例1輸出】
1
【樣例1說明】
只有電線(1,4)滿足
【樣例2輸入】
4 4 1 2 2 3 3 2 4 3
【樣例2輸出】
2
【樣例2說明】
電線(1,2)和(3,4)滿足要求
【數據範圍】
對於10%的數據,滿足 n ≤ 1000 , m ≤ 2000
對於另外10%的數據,滿足 m = n
對於另外35%的數據,滿足 m ≤ n + 100
對於100%的數據,滿足 2 ≤ n ≤ 100000 , 1 ≤ m ≤ 200000
題目翻譯
對一個無向圖,尋找有多少條邊滿足:刪去這條邊後,使圖爲二分圖,且這條邊的端點不在二分圖的同一側
二層翻譯
尋找有多少條邊滿足:圖中所有奇環都包含這條邊,且這條邊不屬於任何偶環
直接說100%數據的做法
建一棵DFS樹,通過返祖邊找環
對每個點記錄一個cnt,當返祖邊u->v形成奇環(染色法判斷)時cnt[u]++,cnt[v]--,偶環時反過來,並確定這條邊一定不能被選。這樣以後u的子樹內所有的cnt之和就表示了u->fa這條邊被多少奇環包含(差分前綴和思想)。
code
#include<bits/stdc++.h>//正式比賽別亂用
using namespace std;
struct mzls
{
int to,id;
}as;
vector<mzls>g[100005];
bool c[100005],f[100005],f1[200005];//注意邊和點不同的範圍
int cnt[200005],tot[200005],n,m,ans,t1;
inline void dfs(int u)
{
f[u]=1;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].to,d=g[u][i].id;
if(f1[d])
continue;
f1[d]=1;
if(f[v]&&c[v]==c[u])//顏色相同時爲奇環
{
t1++;//記錄圖中所有的奇環
cnt[u]++;
cnt[v]--;
tot[d]++;
continue;
}
if(f[v])
{
cnt[v]++;
cnt[u]--;
tot[d]--;//這裏被減了以後d這條邊永遠不可能被選
continue;
}
c[v]=!c[u];//交叉染色
dfs(v);
tot[d]+=cnt[v];
cnt[u]+=cnt[v];//從下往上傳
}
}
int main()
{
//freopen("voltage.in","r",stdin);
//freopen("voltage.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
as.to=y,as.id=i;//每條邊單獨記錄id,因爲兩點之間可以有重邊
g[x].push_back(as);
as.to=x;
g[y].push_back(as);
}
dfs(1);
for(int i=1;i<=m;i++)
if(tot[i]==t1)
ans++;
printf("%d\n",ans);
}