洛谷P2319 [HNOI2006]超级英雄

一开始是用二分图匹配(网络流)+二分做的,后来发现直接用匈牙利更简单

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define pii pair<int,int>
#define X first
#define Y second
#define INF 0x7f7f7f7f
#define MAXN 1000+10
using namespace std;
struct Edge{
    int from,to,cap,flow;
    Edge(int u=0,int v=0,int c=0,int f=0){
        from=u,to=v,cap=c,flow=f;
    }
};
struct Dinic{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[MAXN<<1];
    int d[MAXN<<1];
    int b[MAXN<<1];
    int cur[MAXN<<1];
    void init(int n,int s,int t){
        this->n=n;
        this->s=s,this->t=t;
        edges.clear();
        for(int i=0;i<=n;i++){
            G[i].clear();
        }
    }
    void AddEdge(int x,int y,int cap){
        edges.push_back(Edge(x,y,cap,0));
        edges.push_back(Edge(y,x,0,0));
        m=edges.size();
        G[x].push_back(m-2);
        G[y].push_back(m-1);
    }
    bool BFS(){
        memset(b,0,sizeof(b));
        queue<int> q;
        d[s]=1;
        q.push(s);
        b[s]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge &e=edges[G[x][i]];
                if(e.cap>e.flow&&!b[e.to]){
                    q.push(e.to);
                    b[e.to]=1;
                    d[e.to]=d[x]+1;
                }
            }
        }
        return b[t];
    }
    int dfs(int x,int a){
        if(x==t||!a)return a;
        int flow=0,f;
        for(int &i=cur[x];i<G[x].size();i++){
            Edge &e=edges[G[x][i]];
            if(d[e.to]==d[x]+1&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
                edges[G[x][i]].flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(!a){
                    break;
                }    
            }
        }
        return flow;
    }
    int Maxflow(){
        int flow=0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow+=dfs(s,INF);
        }
        return flow;
    }
}D;
int n,m;
pii a[MAXN];
int s[MAXN];
void print(int x){
    for(int i=0;i<D.edges.size();i++){
        Edge &e=D.edges[i];
        if(e.flow>=1&&n+1<=e.to&&e.to<=n+x){
            s[e.to-n]=e.from;
        }
    }
    for(int i=1;i<=x;i++){
        printf("%d\n",s[i]-1);
    }
}
void init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a[i].X,&a[i].Y);
        a[i].X++,a[i].Y++;
    }
}
int check(int x){
    D.init(n+x+2,0,n+x+1);
    for(int i=1;i<=n;i++){
        D.AddEdge(0,i,1);
    }    
    for(int i=1;i<=x;i++){
        D.AddEdge(a[i].X,n+i,1);
        D.AddEdge(a[i].Y,n+i,1);
        D.AddEdge(n+i,n+x+1,1);
    }
    int ans=D.Maxflow();
    return (ans==x);
}
void solve(){
    int L=0,R=m;
    while(R-L>1){
        int mid=(L+R)/2;
        if(check(mid)){
            L=mid;
        }
        else{
            R=mid;
        }
    }
    if(check(R)){
        printf("%d\n",R);
        print(R);
    }
    else if(check(L)){
        printf("%d\n",L);
        print(L);
    }
}
int main()
{
    //freopen("data.in","r",stdin);
    init();
    solve();
    return 0;
}

 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define pii pair<int,int>
#define X first
#define Y second
#define INF 0x7f7f7f7f
#define MAXN 1000+10
using namespace std;
int n,m;
int girl[MAXN],boy[MAXN];
int used[MAXN];
int a[MAXN][2];
bool find(int x){
    for(int i=0;i<=1;i++){
        int y=a[x][i];
        if(!used[y]){
            used[y]=1;
            if(!girl[y]||find(girl[y])){
                girl[y]=x;
                boy[x]=y;
                return 1;
            }    
        }
    }
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        x++,y++;
        a[i][0]=x,a[i][1]=y;
    }
    int ans=0;
    for(int i=1;i<=m;i++){
        memset(used,0,sizeof(used));
        if(find(i))
            ans++;
        else
            break;
    }
    printf("%d\n",ans);
    for(int i=1;i<=ans;i++){
        printf("%d\n",boy[i]-1);
    }
    return 0;
}

 

posted @ 2017-12-19 00:43  white_hat_hacker  阅读(162)  评论(0编辑  收藏  举报