您的位置:首页 > 其它

HDU 6073 Matching In Multiplication(拓扑排序+思维)

2017-08-07 17:11 435 查看
http://acm.hdu.edu.cn/showproblem.php?pid=6073

题意:
有个二分图,左边和右边的顶点数相同,左边的顶点每个顶点度数为2。现在有个屌丝理解错了最佳完美匹配,它以为最佳完美匹配是边权的乘积了,现在要你计算所有这种最佳完美匹配的边权乘积和。保证至少存在一个完美匹配。

思路:

这道题目虽然打着二分图的幌子,但其实吧,根本就不是二分图,哎。

对于右边的点来说,如果它的度数为1,那么与它匹配的点肯定是确定的,所以我们先通过拓扑排序来计算出所有确定的匹配。去除这些点后,假设左边和右边各还剩下x个点,此时还有2x条边,此时右边顶点每个顶点的度数必为2。

此时其实就是连通图,对于左边的每一个顶点,它都有两种边可供选择,然而一旦确定了一条边之后,整个环就都确定下来了,所以对于一个环来说共有两种选择方法。

参考了大神的dfs方法,太强了!!!

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=3e5+5;
const int mod=998244353;

int n;
int tot, head[2*maxn];
int del[2*maxn], deg[maxn];
ll res[3];

struct node
{
int v, w, next;
int mark;
}e[4*maxn];

void addEdge(int u, int v, int w)
{
e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; e[tot].mark=0;
head[u]=tot++;
}

void init()
{
tot=0;
memset(head,-1,sizeof(head));
memset(deg,0,sizeof(deg));
memset(del,0,sizeof(del));
}

void dfs(int u, int flag)
{
del[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
if(e[i].mark)  continue;
int v=e[i].v;
e[i].mark=e[i^1].mark=1;
res[flag]=(res[flag]*e[i].w)%mod;
dfs(v,flag^1);
}
}

int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int v1,d1,v2,d2;
scanf("%d%d%d%d",&v1,&d1,&v2,&d2);
addEdge(i,v1+n,d1); addEdge(v1+n,i,d1);
addEdge(i,v2+n,d2); addEdge(v2+n,i,d2);
deg[v1]++; deg[v2]++;
}

ll ans=1;
queue<int> Q;
for(int i=1;i<=n;i++)
if(deg[i]==1)  Q.push(i+n);

while(!Q.empty())
{
int u=Q.front(); Q.pop();
del[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)  //左边
{
if(e[i].mark)  continue;
int v=e[i].v;
del[v]=1;
e[i].mark=e[i^1].mark=1;
ans=(ans*e[i].w)%mod;

for(int j=head[v];j!=-1;j=e[j].next)  //右边
{
if(e[j].mark)  continue;
int p=e[j].v;
deg[p-n]--;
e[j].mark=e[j^1].mark=1;
if(deg[p-n]==1)  Q.push(p);
}
}
}

for(int i=1;i<=n;i++)
{
if(!del[i])
{
res[0]=res[1]=1;
dfs(i,0);
ans=(ans*((res[0]%mod+res[1]%mod)%mod))%mod;
}
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐