zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/48

    一道二分图匹配,跑费用流就可以过了(其实最大流都可以了)。

    #include<bits/stdc++.h>
    #define MAXN_ 5050
    #define INF 0x3f3f3f3f
    #define P pair<int,int>
    using namespace std;
    struct edge {
        int to,cap,cost,rev;
    };
    int n,m,flow,s,t,cap,res,cost,from,to,h[MAXN_];
    std::vector<edge> G[MAXN_];
    int dist[MAXN_],prevv[MAXN_],preve[MAXN_]; // 前驱节点和对应边
    inline void add() {
        G[from].push_back((edge) {
            to,cap,cost,(int)G[to].size()
        });
        G[to].push_back((edge) {
            from,0,-cost,(int)G[from].size()-1
        });
    } // 在vector 之中找到边的位置所在!
    inline int read() {
        int x=0;
        char c=getchar();
        bool flag=0;
        while(c<'0'||c>'9') {
            if(c=='-')
                flag=1;
            c=getchar();
        }
        while(c>='0'&&c<='9') {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        return flag?-x:x;
    }
    inline void min_cost_flow(int s,int t,int f) {
        fill(h+1,h+1+n,0);
        while(f > 0) {
            priority_queue<P,vector<P>, greater<P> > D;
            memset(dist,INF,sizeof dist);
            dist[s] = 0;
            D.push(P(0,s));
            while(!D.empty()) {
                P now = D.top();
                D.pop();
                if(dist[now.second] < now.first)
                    continue;
                int v = now.second;
                for(int i=0; i<(int)G[v].size(); ++i) {
                    edge &e = G[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        D.push(P(dist[e.to],e.to));
                    }
                }
            }
            // 无法增广 , 就是找到了答案了!
            if(dist[t] == INF)
                break;
            for(int i=1; i<=n; ++i)
                h[i] += dist[i];
            int d = f;
            for(int v = t; v != s; v = prevv[v])
                d = min(d,G[prevv[v]][preve[v]].cap);
            f -= d;
            flow += d;
            res += d * h[t];
            for(int v=t; v!=s; v=prevv[v]) {
                edge &e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
    }
    int main() {
        int n1,n;
        scanf("%d",&n1);
        scanf("%d",&n);
    
    
    
        //n = read();
        //m = read();
        //s = read();
        //t = read();
        s=0;
        t=n+1;
        while(1) {
            from = read();
            to = read();
            if(from==-1&&to==-1)
                break;
            //cap = read();
            //cost = read();
            cap=1;
            cost=1;
            add();
        }
    
        for(int i=1;i<=n1;i++){
            from=s;
            to=i;
            cap=1;
            cost=1;
            add();
        }
    
        for(int i=n1+1;i<=n;i++){
            from=i;
            to=t;
            cap=1;
            cost=1;
            add();
        }
        min_cost_flow(s,t,INF);
        //printf("%d %d
    ",flow,res);
        printf("%d
    ",flow);
        return 0;
    }

    洛谷上的居然要求出是哪些边。

    那就根据自己丰富的编程经验瞎搞一发。

    #include<bits/stdc++.h>
    #define MAXN_ 5050
    #define INF 0x3f3f3f3f
    #define P pair<int,int>
    using namespace std;
    struct edge {
        int to,cap,cost,rev;
    };
    int n,m,flow,s,t,cap,res,cost,from,to,h[MAXN_];
    std::vector<edge> G[MAXN_];
    int dist[MAXN_],prevv[MAXN_],preve[MAXN_]; // 前驱节点和对应边
    inline void add() {
        G[from].push_back((edge) {
            to,cap,cost,(int)G[to].size()
        });
        G[to].push_back((edge) {
            from,0,-cost,(int)G[from].size()-1
        });
    } // 在vector 之中找到边的位置所在!
    inline int read() {
        int x=0;
        char c=getchar();
        bool flag=0;
        while(c<'0'||c>'9') {
            if(c=='-')
                flag=1;
            c=getchar();
        }
        while(c>='0'&&c<='9') {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        return flag?-x:x;
    }
    inline void min_cost_flow(int s,int t,int f) {
        fill(h+1,h+1+n,0);
        while(f > 0) {
            priority_queue<P,vector<P>, greater<P> > D;
            memset(dist,INF,sizeof dist);
            dist[s] = 0;
            D.push(P(0,s));
            while(!D.empty()) {
                P now = D.top();
                D.pop();
                if(dist[now.second] < now.first)
                    continue;
                int v = now.second;
                for(int i=0; i<(int)G[v].size(); ++i) {
                    edge &e = G[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        D.push(P(dist[e.to],e.to));
                    }
                }
            }
            // 无法增广 , 就是找到了答案了!
            if(dist[t] == INF)
                break;
            for(int i=1; i<=n; ++i)
                h[i] += dist[i];
            int d = f;
            for(int v = t; v != s; v = prevv[v])
                d = min(d,G[prevv[v]][preve[v]].cap);
            f -= d;
            flow += d;
            res += d * h[t];
            for(int v=t; v!=s; v=prevv[v]) {
                edge &e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
    }
    int main() {
        int n1,n;
        /*1~n1 英国 n1~n 外国*/
        scanf("%d",&n1);
        scanf("%d",&n);
        n+=n1;
    
        //n = read();
        //m = read();
        //s = read();
        //t = read();
        s=0;
        t=n+1;
    
        int cnt=0;
        while(1) {
            from = read();
            to = read();
            if(from==-1&&to==-1)
                break;
            //cap = read();
            //cost = read();
            /*手动设置容量和费用为1*/
            cap=1;
            cost=1;
            add();
            cnt+=2;
        }
    
        /*手动添加超级源点和超级汇点*/
        for(int i=1;i<=n1;i++){
            from=s;
            to=i;
            cap=1;
            cost=1;
            add();
            cnt+=2;
        }
    
        for(int i=n1+1;i<=n;i++){
            from=i;
            to=t;
            cap=1;
            cost=1;
            add();
            cnt+=2;
        }
    
    
        vector<pair<int,int> >ans;
        min_cost_flow(s,t,INF);
        if(flow){
            for(int i=1;i<=n1;i++){
                for(auto j:G[i]){
                    if(j.to!=s&&j.cap==0){
                        ans.push_back({i,j.to});
                    }
                }
            }
    
            printf("%d
    ",ans.size());
            for(auto i:ans){
                printf("%d %d
    ",i.first,i.second);
            }
        }
        else{
            printf("No Solution!
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    样式超出设定宽度显示显示省略号
    客户端存在潜在危险request.from
    MenuStrip如何设置快捷键
    SVN的使用方法
    长串英文字符不换行的解决办法
    thickbox使用
    System.Web.UI.UserControl”,因此此处不允许
    C#中实现拖动无边框Form窗体和窗体的起始位置
    (转)Altera Forum精彩问答汇总
    (转)如何以32 bit的方式存取SDRAM?
  • 原文地址:https://www.cnblogs.com/Yinku/p/10425071.html
Copyright © 2011-2022 走看看