zoukankan      html  css  js  c++  java
  • UVa 1349 (二分图最小权完美匹配)

    题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4095

    由于每个点只属于一个有向圈,也就是每个点都只有一个唯一的后继
    反之,每个点都有一个唯一的后继,每个点也恰好属于一个圈

    于是想到二分图,将每个点 (i) 拆成 (X_i)(Y_i),有向边 ((u,v)) 对应 (X_u) -> (Y_v), 求出最小权完美匹配即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 505;
    const int INF = 1000000007;
    
    int n;
    
    int h[maxn], cnt = 1;
    struct E{
    	int from, to, cost, cap, next;
    }e[maxn * maxn * 100];
    void add(int u, int v, int w, int c){
    	e[++cnt].to = v;
    	e[cnt].from = u;
    	e[cnt].cost = w;
    	e[cnt].cap = c;
    	e[cnt].next = h[u];
    	h[u] = cnt;
    }
    
    int inq[maxn];         // 是否在队列中
      int d[maxn];           // Bellman-Ford
      int p[maxn];           // 上一条弧
      int a[maxn];           // 可改进量
      bool BellmanFord(int s, int t, int& flow, int& cost) {
        for(int i = 1 ; i <= n + n + 2 ; ++i) d[i] = INF;
        memset(inq, 0, sizeof(inq));
        memset(a, 0, sizeof(a));
        d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
    
        queue<int> Q;
        Q.push(s);
        while(!Q.empty()) {
          int u = Q.front(); Q.pop();
          inq[u] = 0;
          for(int i = h[u]; i != -1 ; i = e[i].next) {
            if(e[i].cap && d[e[i].to] > d[u] + e[i].cost) {
              d[e[i].to] = d[u] + e[i].cost;
              p[e[i].to] = i;
              a[e[i].to] = min(a[u], e[i].cap);
              if(!inq[e[i].to]) { Q.push(e[i].to); inq[e[i].to] = 1; }
            }
          }
        }
        if(d[t] == INF) return false;
        
        flow += a[t];
        cost += d[t] * a[t];
        for(int u = t; u != s; u = e[p[u]].from) {
          e[p[u]].cap -= a[t];
          e[p[u]^1].cap += a[t];
        }
        return true;
      }
    
      // 需要保证初始网络中没有负权圈
      int MincostFlow(int s, int t, int& cost) {
        int flow = 0; cost = 0;
        while(BellmanFord(s, t, flow, cost));
        return flow;
      }
    
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	while(scanf("%d", &n) == 1 && n){
    		memset(h, -1, sizeof(h)); cnt = 1;
    		
    		int u, v;
    		for(int i = 1 ; i <= n ; ++i){
    			while(scanf("%d", &u) == 1 && u){
    				scanf("%d", &v);
    				add(i, u + n, v, 1);
    				add(u + n, i, -v, 0);
    			}
    		}
    		
    		int s = n + n + 1, t = n + n + 2;
    		for(int i = 1 ; i <= n ; ++i){ // 源点 -> X 
    			add(s, i, 0, 1);
    			add(i, s, 0, 0);
    		}
    		for(int i = 1 ; i <= n ; ++i){ // Y -> 汇点 
    			add(i + n, t, 0, 1);
    			add(t, i + n, 0, 0);
    		}
    		
    		int flow = 0, cost = 0;
    		flow = MincostFlow(s, t, cost);
    		
    		if(flow == n){
    			printf("%d
    ", cost);
    		} else{
    			printf("N
    ");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS应用内支付(内购)的个人开发过程及坑!
    AJAX实现仿Google Suggest效果
    jquery的show/hide性能测试
    如何做到尽可能不使用庞大的jQuery
    CSS3 transition规范的实际使用经验
    jQuery提升性能技巧及个人总结
    使用CSS3实现超炫的Loading(加载)动画效果
    一个有趣的Ajax Hack示范
    使用ajax技术无刷新动态调用股票信息
    将Asp.Net页面输出到EXCEL里去
  • 原文地址:https://www.cnblogs.com/tuchen/p/14998062.html
Copyright © 2011-2022 走看看