您的位置:首页 > 其它

bzoj1143[CTSC2008]祭祀river

2015-12-13 20:18 471 查看
果然超神的一道题,但是bzoj上面没有第二问额……好吧暂时第二问只有暴力的想法

但是我们可以思考出第一问。

大致就是,因为如果在一个地方建了,那么这个地方能够流到的地方统统都不能建。于是我们可以贪心的思考,我们可以使能够流到的一片所组成的图最小。

而且很显然答案一定会覆盖整幅图,所以我们就想到了floyed处理出每个点能够流通到的地方,然后对于这个做一个最大匹配。然而我不知道为什么……

于是:


来自cxjyxx_me的。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 105
#define M 1005
int a

;
int n,m;
bool c

;
int l
,ans=0;
bitset<N>y;

void floyed()
{
//	memset(c,0,sizeof(c));
fo(k,1,n)
{
fo(i,1,n)
if(k!=i)
{
fo(j,1,n)
if(i!=j)
{
if(a[i][k]&&a[k][j]) c[i][j]=1;
//				if(c[i][j])cout<<i<<' '<<j<<endl;
}
}
}
}

bool match(int x)
{
fo(i,1,n)
if(y[i]==0&&c[x][i])
{
y[i]=1;
if(l[i]==0||match(l[i]))
{
l[i]=x;
return 1;
}
}
return 0;
}

void work()
{
memset(l,0,sizeof(l));
fo(i,1,n)
{
y.reset();
if(match(i))ans++;
}
}

void check()
{
fo(i,1,n)
fo(j,1,n)
if(i!=j&&c[i][j]) cout<<i<<' '<<j<<endl;
}

int main()
{
memset(c,0,sizeof(c));
n=read(),m=read();
fo(i,1,m)
{
int x=read(),y=read();
a[x][y]=1;
c[x][y]=1;
}
floyed();
//	check();
work();
cout<<n-ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分图匹配