HDU6073Matching In Multiplication

来源:互联网 发布:深圳淘宝大学培训 编辑:程序博客网 时间:2024/05/22 03:46

题目链接

题意

​ 存在两个点集 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 longconst 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);    }}