1854: [Scoi2010]游戏

来源:互联网 发布:windows功能哪些不能关 编辑:程序博客网 时间:2024/05/20 14:39

题目链接

题目大意:给定n个武器,每个武器有两个属性,只能使用其中一个,要求选择一些武器 可以造成形如1 2 3 4的伤害 求最大伤害

题解:有比较naive的二分图匹配做法:武器->一边点集,属性->一边点集,连边,枚举属性进行匹配,时间玄学

神奇的并查集做法

我的收获:思想神啊

二分图匹配

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int M=1000005;int n,m,T,t;int head[M],lik[M],vis[M];struct edge{int to,nex;}e[M*4];void add(int u,int v){e[t]=(edge){v,head[u]};head[u]=t++;}bool hungary(int x){    for(int i=head[x];i!=-1;i=e[i].nex){        int v=e[i].to;        if(vis[v]==T) continue;        vis[v]=T;        if(!lik[v]||hungary(lik[v])) return lik[v]=x;    }    return false;}void work(){    int ans=0;    for(int i=1;i<=10000;i++){        ++T;        if(hungary(i)) ans++;        else break;    }    cout<<ans<<endl;}void init(){    cin>>m;    int x,y;memset(head,-1,sizeof(head));    for(int i=1;i<=m;i++){        scanf("%d%d",&x,&y);        add(x,i),add(y,i);    }}int main(){    init();    work();    return 0;}

并查集

#include <iostream>#include <cstdio>using namespace std;int n,fa[10005];bool vis[10005];inline int read(){    char ch=getchar();    int f=1,x=0;    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}    return x*f;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void uniom(int x,int y){    if(y>x) swap(x,y);    if(vis[y]) swap(x,y);    vis[y]=1,fa[y]=x;}void work(){    for(int i=1;i<=n+1;i++)        if(!vis[i]){printf("%d",i-1);return ;}}void init(){    cin>>n;    for(int i=1;i<=10000;i++) fa[i]=i;    for(int i=1;i<=n;i++){        int x=read(),y=read();        int p=find(x),q=find(y);        if(p==q) vis[p]=1;        else uniom(p,q);    }}int main(){    init();    work();     return 0;}
原创粉丝点击