hdu 6073 Matching In Multiplication [dfs]

来源:互联网 发布:第一次戴隐形眼镜知乎 编辑:程序博客网 时间:2024/06/04 21:46

题意:给你2*n个点,左边的n个点都与右边的点连两条边,问所有完全匹配的方案中所有边权相乘之后的和。(不存在重复边)

题解:由于每个左端点只提供两条边,假如一个右端点的度为1的时候,说明这个右端点的匹配是确定的,然后将这个匹配点的连边删除,不断判断是否有度为1的点。最后剩下的点,必定都是度为2的点。剩下的图为多个环的图,环之间的匹配方案相互独立,且只有两种方案,所以根据母函数的定义,总的和为(w1+w2)*(w3+w4)······(w为一个环中的一种方案数)。

AC代码:

#include<stdio.h>#include<vector>#include<string.h>#include<queue>#include<iostream>#include<map>#define N 600005#define mod 998244353using namespace std;typedef long long ll;struct node{    ll v,w;    node(){}    node(ll v,ll w)    {        this->v=v;        this->w=w;    }};struct edge{ll to,w,next;edge(){}edge(int to,int w,int next){this->to=to;this->w=w;this->next=next;}}ed[N*2];int head[N],lnum;void addline(int a,int b,int w){ed[lnum]=edge(b,w,head[a]);head[a]=lnum++;}ll ans,n;ll mark[N];ll du[N];ll flag=0;void dfs(ll pos,ll sum1,ll sum2,ll from,ll ff){    if(flag==1)return ;    ll f=0;    for(ll i=head[pos];~i;i=ed[i].next)    {    ll to=ed[i].to;   if(mark[to]==1||to==from)continue;    f=1;    mark[to]=1;    if(!ff)dfs(to,sum1*ed[i].w%mod,sum2,pos,ff^1);    else dfs(to,sum1,sum2*ed[i].w%mod,pos,ff^1);    if(flag==1)return ;    }    if(f==0)   {   ans=ans*(sum1+sum2)%mod;   flag=1;}}int main(){    ll T;    scanf("%lld",&T);    while(T--)    {        ans=1;        memset(du,0,sizeof(du));        memset(mark,0,sizeof(mark));        memset(head,-1,sizeof(head));        lnum=0;        scanf("%lld",&n);        for(ll i=1;i<=n;i++)        {            ll a,w1,b,w2;            scanf("%lld%lld%lld%lld",&a,&w1,&b,&w2);            addline(i,a+n,w1%mod);            addline(a+n,i,w1%mod);            addline(i,b+n,w2%mod);            addline(b+n,i,w2%mod);            du[i]++;du[a+n]++;            du[i]++;du[b+n]++;        }        queue<ll>que;        for(ll i=1;i<=2*n;i++)            if(du[i]==1)        que.push(i);        while(!que.empty())        {            ll k=que.front();            que.pop();            ll to;            for(int i=head[k];~i;i=ed[i].next)            if(mark[ed[i].to]==0){ans=(ans*ed[i].w)%mod;to=ed[i].to;break;}            mark[k]=mark[to]=1;            for(ll i=head[to];~i;i=ed[i].next)            {            ll y=ed[i].to;            if(mark[y]==1)continue;            du[y]--;            if(du[y]==1)que.push(y);            }        }        for(ll i=1;i<=2*n;i++)        {            flag=0;            if(mark[i]==0)            {                dfs(i,1,1,-1,0);                mark[i]=1;            }        }        printf("%lld\n",ans);    }}


原创粉丝点击