1. 程式人生 > >[BZOJ]4238: 電壓

[BZOJ]4238: 電壓

main mst 不用 rdquo online || https += script

 題解: 一眼看過去 大討論題? 什麽奇偶環討論下? 然後仔細考慮一下 我們對於所有的邊分成樹邊和非樹邊 對於所有的非樹邊 能形成奇環的在路徑上的邊+1 形成偶環的路徑上-1 然後看邊上權值等於奇環數量的就是可以被選擇的.....不用其他高級數據結構維護 看了discuss好像帶log會T...那就老實在 u,v節點和 其lca位置打上標記 做個差分就可以求出每條邊的權值 然後統計貢獻即可

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
int n,m;
typedef struct node{
    int u,v;
}node;
vector<node>vec;
int f[MAXN];
int fa[MAXN],son[MAXN],num[MAXN],dep[MAXN];
int sum[MAXN];

int find1(int x){
    if(x==f[x])return x;
    else return f[x]=find1(f[x]);
}
void dfs(int x,int pre,int deep){
    fa[x]=pre;num[x]=1;dep[x]=deep+1;
    link(x){
	if(j->t==pre)continue;
	dfs(j->t,x,deep+1);
	num[x]+=num[j->t];
	if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
    }
}
int tp[MAXN];
void dfs1(int x,int td){
    tp[x]=td;
    if(son[x]!=-1)dfs1(son[x],td);
    link(x)if(j->t!=son[x]&&j->t!=fa[x])dfs1(j->t,j->t);
}

int Lca(int x,int y){
    int xx=tp[x];int yy=tp[y];
    while(xx!=yy){
	if(dep[xx]<dep[yy])swap(xx,yy),swap(x,y);
	x=fa[xx];xx=tp[x];
    }
    if(dep[x]>dep[y])swap(x,y);
    return x;
}

void dfs2(int x){
    link(x){
	if(j->t==fa[x])continue;
	dfs2(j->t);
	sum[x]+=sum[j->t];
    }
}

bool vis[MAXN];
int main(){
    n=read(),m=read();
    inc(i,1,n)f[i]=i,son[i]=-1;
    int u,v;
    while(m--){
	u=read();v=read();
	int t1=find1(u);int t2=find1(v);
	if(t1==t2){vec.pb((node){u,v});continue;}
	f[t1]=t2;add(u,v);add(v,u);
    }
    inc(i,1,n)if(!dep[i])dfs(i,0,0),dfs1(i,i),vis[i]=1,sum[i]=-1;
    int cnt=0;
    for(int i=0;i<vec.size();i++){
	u=vec[i].u;v=vec[i].v;
	if(u>v)swap(u,v);
	int lca=Lca(u,v);
	int t=dep[u]+dep[v]-2*dep[lca]+1;
	if(t&1){
	    cnt++,sum[u]++,sum[v]++,sum[lca]-=2;
	}
	else sum[u]--,sum[v]--,sum[lca]+=2;
    }
    int ans=0;
    if(cnt==1)ans++;
    inc(i,1,n)if(vis[i])dfs2(i);
    inc(i,1,n)if(cnt==sum[i])ans++;
    printf("%d\n",ans);
}

  

4238: 電壓

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 567 Solved: 252
[Submit][Status][Discuss]

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

[BZOJ]4238: 電壓