HDU6073 Matching In Multiplication

題目鏈接

題意

​ 存在兩個點集 U,V ,點集 U 中的每個點均向 V 連出兩條帶權無向邊,選擇特定的邊能使 U,V 構成一個完全二分圖。定義一個完全二分圖的值爲其所有邊權值的乘積,求解 U,V 能構成的所有完全二分圖的值的和。

分析

​ 注意到要構成完全二分圖,即每個點要且僅被一條邊所連接。所以考慮度數不確定的點集 V ,對於所有度數爲1的點均是僅一種選擇,小編採用搜索的方法對所有度數爲1的點進行與確認,通過0,1交換的方式鑑別對應邊是否肯定會被選中。遞歸的去除完所有度數爲1的點後,剩下的部分必然組成 k 個聯通塊,同時每個點的度數 2 。設剩餘 m 個點,點集 U 中的每個點度數爲2,即剩餘2m 條邊,而點集 V 中有 m 個點,且度數 2 ,顯然 V 中每個點的度數也均爲2。連通塊中所有點的度數均爲2,則該聯通塊必然是一個環,那麼構建完全二分圖在該聯通塊中只需要間隔着取邊即可,共2中方案。剩下的問題是如何計算,我們發現對於兩個聯通塊,假設其建圖後值分別爲 a,bc,d 。那麼最後的值爲 ac+ad+bc+bd=a(c+d)+b(c+d)=(a+b)(c+d) 。故對每個聯通塊分別計算就能得到最後的答案了。詳細不理解的對方可以看代碼。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 300300
#define eps 1e-7
#define lson rt<<1
#define rson rt<<1|1
#define LL long long
const int mod=998244353;
struct Edge{
    int v;
    LL w;
    Edge(){}
    Edge(int _v,LL _w):v(_v),w(_w){}
};
vector<Edge> edge;
vector<int> g[MAXN*2];
int deg[MAXN*2];
int vis[MAXN*2];
LL cnt[2];
LL ans;
void addedge(int u,int v,LL w){
    g[u].push_back(edge.size());
    edge.push_back(Edge(v,w));
    deg[u]++;
}
void dfs(int u,int f,int flg){
    vis[u]=1;
    for(int i=0;i<g[u].size();++i){
        Edge &e = edge[g[u][i]];
        if(vis[e.v])
            continue;
        deg[e.v]--;
        if(flg)
            ans=(ans*e.w)%mod;
        if(deg[e.v]==1)
            dfs(e.v,u,1-flg);
    }
}
void dfs2(int u,int f,int idx){
    for(int i=0;i<g[u].size();++i){
        Edge &e = edge[g[u][i]];
        if(e.v==f || vis[e.v])
            continue;
        vis[e.v]=1;
        cnt[idx]=(cnt[idx]*e.w)%mod;
        dfs2(e.v,u,1-idx);
    }
}
int main(){
    int T,n,v;
    LL w;
    cin>>T;
    while(T--){
        scanf("%d",&n);
        edge.clear();
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=2*n;++i){
            g[i].clear();
            deg[i]=0;
        }
        for(int i=1;i<=n;++i){
            for(int k=0;k<2;++k){
                scanf("%d %I64d",&v,&w);
                v+=n;
                addedge(i,v,w);
                addedge(v,i,w);
            }
        }
        ans=1;
        for(int i=n+1;i<=2*n;++i)
            if(deg[i]==1)
                dfs(i,0,1);
        for(int i=1;i<=2*n;++i)
            if(!vis[i]){
                cnt[0]=cnt[1]=1;
                dfs2(i,0,0);
                ans=(ans*(cnt[0]+cnt[1]))%mod;
            }
        printf("%I64d\n",ans);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章