[SCOI2010]连续攻击游戏

来源:互联网 发布:youtube无网络连接ios 编辑:程序博客网 时间:2024/04/28 01:58

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。现在lxhgww想知道他最多能连续攻击boss多少次?
输入格式:
输入的第一行是一个整数N,表示lxhgww拥有N种装备接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值
输出格式:
输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

这道题啊。。看到题觉得和魔术球问题很像然后就跑了一个复杂度为O(我觉得能过)的网络流。。
然后就T了5个点。
后来二分图用匈牙利就跑过了。。里面用了一点小技巧(用了时间戳而不是初始化数组)
本题并查集做法详见黄学长博客:会害羞的小女巫打开的传送门~~

网络流50分:#include<bits/stdc++.h>using namespace std;const int INF=1e9;const int MAXN=2e6+5;struct edge{    int to,next,w;}e[MAXN<<3];int head[MAXN],cur[MAXN],cnt=1;inline void add(int u,int v,int w){e[++cnt]=(edge){v,head[u],w},head[u]=cnt;}int n,s,t;int dep[MAXN];queue<int>q;bool bfs(int x){    memset(dep,0,sizeof(dep));    q.push(x);dep[x]=1;    while(q.size()){        int u=q.front();q.pop();        for(int i=head[u];i;i=e[i].next){            int v=e[i].to,w=e[i].w;            if(w&&!dep[v]){                dep[v]=dep[u]+1;q.push(v);            }        }    }    if(!dep[t])return 0;    return 1;}int dfs(int u,int flow){    if(u==t||flow==0)return flow;    for(int &i=cur[u];i;i=e[i].next){        int v=e[i].to,w=e[i].w;        if(w&&dep[v]==dep[u]+1){            int tem=dfs(v,min(flow,w));            if(tem){                e[i].w-=tem;                e[i^1].w+=tem;                return tem;            }        }    }    return 0;}int dinic(){    int ans=0;    while(bfs(s)){        for(int i=s;i<=t;i++)cur[i]=head[i];        while(int d=dfs(s,INF))ans+=d;    }    return ans;}int main(){    scanf("%d",&n);    s=0;t=n+10001;    int tem1,tem2;    for(int i=1;i<=n;i++){        scanf("%d%d",&tem1,&tem2);        add(s,i,1),add(i,s,0);        add(i,n+tem1,1),add(n+tem1,i,0);        add(i,n+tem2,1),add(n+tem2,i,0);    }    int ans=0,ok=0,dq=0;    do{        ++dq;        ++ans;        add(n+dq,t,1),add(t,n+dq,0);        ok=dinic();    }while(ok);    printf("%d\n",--ans);    return 0;}
匈牙利AC:#include<bits/stdc++.h>using namespace std;const int INF=1e9;const int MAXN=3e6+5;struct edge{    int to,next;}e[MAXN<<3];int head[MAXN],link[MAXN],cnt=1;int vis[MAXN],id;inline void add(int u,int v){e[++cnt]=(edge){v,head[u]},head[u]=cnt;}int n;int dfs(int u){    for(int i=head[u];i;i=e[i].next){        int v=e[i].to;        if(vis[v]!=id){            vis[v]=id;            if(!link[v]||dfs(link[v])){                link[v]=u;                return 1;            }        }    }    return 0;}int Hungarian(){    int ans = 0;    for(int i=n+1; i<=n+10000;i++){        ++id;        if(dfs(i)) ans++;        else return ans;    }    return ans;}int main(){    memset(link,0,sizeof(link));    scanf("%d",&n);    int tem1,tem2;    for(int i=1;i<=n;i++){        scanf("%d%d",&tem1,&tem2);        add(n+tem1,i),add(n+tem2,i);        //add(i,n+tem1),add(i,n+tem2);    }    printf("%d\n",Hungarian());    return 0;}