【BZOJ 3569】DZY Loves Chinese II

題面

Description

神校XJ之學霸兮,Dzy皇考曰JC。node

攝提貞於孟陬兮,唯庚寅Dzy以降。ios

紛Dzy既有此內美兮,又重之以修能。git

遂降臨於OI界,欲以神力而凌♂辱衆生。搜索引擎

今Dzy有一魞歄圖,其上有N座祭壇,又有M條膴蠁邊。spa

時而Dzy狂WA而怒髮衝冠,神力外溢,遂有K條膴蠁邊灰飛煙滅。code

然後俟其日A50題則又令其復原。(可視爲當即復原)索引

然如有祭壇沒法相互到達,Dzy之神力便會大減,因而欲知其是否連通。ip

Input

第一行N,Mget

接下來M行x,y:表示M條膴蠁邊,依次編號input

接下來一行Q

接下來Q行:

每行第一個數K然後K個編號c1~cK:表示K條邊,編號爲c1~cK

爲了體如今線,c1~cK均需異或以前回答爲連通的個數

Output

對於每組詢問,輸出到輸出文件zap.out一個正整數,表示知足條件的整數對數。

對於每一個詢問輸出:連通則爲‘Connected’,不連通則爲‘Disconnected’

(不加引號)

Sample Input

5 10

2 1

3 2

4 2

5 1

5 3

4 1

4 3

5 2

3 1

5 4

5

1 1

3 7 0 3

4 0 7 4 6

2 2 7

4 5 0 2 13

Sample Output

Connected

Connected

Connected

Connected

Disconnected

Hint

N≤100000 M≤500000 Q≤50000 1≤K≤15

數據保證沒有重邊與自環

Tip:請學會使用搜索引擎

簡明題意

n個點,m條無向邊,求斷掉k條邊後,殘圖是否仍然聯通,強制在線。

題目分析

考慮先構造出原圖的一棵生成樹,對於每條非樹邊rand一個權值。

每條樹邊的權值設爲能夠與當前邊構成迴路的邊的權值異或和。

那麼,若是當前圖不連通,當且僅當一條樹邊被刪除且覆蓋了這條樹邊的全部邊都被刪除了。

此時,這些邊的權值異或起來爲0。

問題轉化爲:

給定邊中是否存在若干個權值異或起來爲0。

此時即可使用線性基求解。


建樹

簡單的建樹操做,任意一棵生成樹都可。

注意用\(fa[ ]\)記錄父親,並用\(use[ ]\)記錄好哪些是樹上的邊,方便以後處理。

void Dfs1(int x){
    vis[x]=1;
    for(int i=h[x];i;i=g[i].next){
        int to=g[i].to;
        if(vis[to])continue;
        use[i>>1]=1,fa[to]=x;
        Dfs1(to);
    }
}

處理邊權

由於此時是一棵樹,因此增長一條邊會且僅會產生一條迴路。

那麼,咱們給一條非樹邊的兩點附上權值,

在上傳的過程當中把該權值附給與父親節點相連的邊,這樣就能夠覆蓋至整條迴路了。

void Dfs2(int x){
    for(int i=h[x];i;i=g[i].next){
        int to=g[i].to;
        if(fa[to]^x)continue;
        Dfs2(to);
        e[i>>1].val^=val[to];
        val[x]^=val[to];
    }
}

for(int i=1;i<=m;i++){
    if(use[i])continue;
    int x=(LL)rand*rand()%1000000000+1;
    e[i].val=x;
    val[e[i].x]^=x,val[e[i].y]^=x;
}

代碼實現

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include<ctime>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=100005,M=500005;
using namespace std;
inline int Getint(){register int x=0,f=1;register 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 h[N],cnt=1;
struct node{int to,next;}g[M<<1];
void AddEdge(int x,int y){g[++cnt].to=y,g[cnt].next=h[x],h[x]=cnt;}
struct Edge{int x,y,val;}e[M];
int fa[N],val[M];
bool vis[N],use[M];
void Dfs1(int x){
    vis[x]=1;
    for(int i=h[x];i;i=g[i].next){
        int to=g[i].to;
        if(vis[to])continue;
        use[i>>1]=1,fa[to]=x;
        Dfs1(to);
    }
}
void Dfs2(int x){
    for(int i=h[x];i;i=g[i].next){
        int to=g[i].to;
        if(fa[to]^x)continue;
        Dfs2(to);
        e[i>>1].val^=val[to];
        val[x]^=val[to];
    }
}
int p[35];
bool Insert(int x){
    for(int i=31;i>=0;i--){
        if(!((x>>i)&1))continue;
        if(!p[i]){p[i]=x;break;}
        x^=p[i];
    }
    return x>0;
}
int main(){
    srand(time(0));
    int n=Getint(),m=Getint();
    for(int i=1;i<=m;i++){
        int x=e[i].x=Getint(),y=e[i].y=Getint();
        AddEdge(x,y),AddEdge(y,x);
    }
    Dfs1(1);
    for(int i=1;i<=m;i++){
        if(use[i])continue;
        int x=(LL)rand()*rand()%1000000000+1;
        e[i].val=x;
        val[e[i].x]^=x,val[e[i].y]^=x;
    }
    Dfs2(1);
    int Q=Getint(),ans=0;
    while(Q--){
        int k=Getint();
        memset(p,0,sizeof(p));
        bool ok=0;
        for(int i=1;i<=k;i++){
            int x=Getint()^ans;
            if(!Insert(e[x].val))ok=1;
        }
        if(!ok)puts("Connected"),ans++;
        else puts("Disconnected");
    }
    return 0;
}
相關文章
相關標籤/搜索