zoukankan      html  css  js  c++  java
  • 星际转移问题(最大流 枚举)

    使用并查集判断有无解,若有解枚举天数若最大流等于人数则可行。

    //http://www.cnblogs.com/IMGavin/
    #include <iostream>
    #include <stdio.h>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <bitset>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    #define gets(A) fgets(A, 1e8, stdin)
    const int INF = 0x3F3F3F3F, N = 10008, MOD = 1003, M = 1000000;
    
    const double EPS = 1e-6;
    int fa[N];
    
    int Find(int x){
        while(x!=fa[x]){
            x=fa[x];
        }
        return x;
    }
    void Union(int x,int y){
        int fx=Find(x);
        int fy=Find(y);
        if(fx!=fy){
            fa[fy]=fx;
        }
    }
    
    int head[N], tot;
    struct node{
    	int u, v, cap, next;
    }edge[M];
    int cur[N], lev[N], s[N];
    
    void init(){
    	memset(head, -1, sizeof(head));
    	tot = 0;
    }
    
    void add(int u, int v, int cap){
    	edge[tot].u = u;
    	edge[tot].v = v;
    	edge[tot].cap = cap;
    	edge[tot].next = head[u];
    	head[u] = tot++;
    //反向弧
    	edge[tot].u = v;
    	edge[tot].v = u;
    	edge[tot].cap = 0;
    	edge[tot].next = head[v];
    	head[v] = tot++;
    }
    
    bool bfs(int st, int des){
    	memset(lev, -1, sizeof(lev));
    	lev[st] = 0;
    	queue<int> q;
    	q.push(st);
    	while(!q.empty()){
    		int u = q.front();
    		q.pop();
    		for(int i = head[u]; i != -1; i = edge[i].next){
    			int v = edge[i].v;
    			if(edge[i].cap && lev[v] == -1){
    				lev[v] = lev[u] + 1;
    				q.push(v);
    				if(v == des){
    					return true;
    				}
    			}
    		}
    	}
    	return false;
    }
    //源点,汇点,点的数量
    int dinic(int st, int des, int n){
    	int ans = 0;
    	while(bfs(st, des)){
    		memcpy(cur, head, sizeof(int) * (n + 1));
    		int u = st, top = 0;
    		while(true){
    			if(u == des){
    				int mini = INF, loc;
    				for(int i = 0; i < top; i++){
    					if(mini > edge[s[i]].cap){
    						mini = edge[s[i]].cap;
    						loc = i;
    					}
    				}
    				for(int i = 0; i < top; i++){
    					edge[s[i]].cap -= mini;
    					edge[s[i] ^ 1].cap += mini;
    				}
    				ans += mini;
    				top = loc;
    				u = edge[s[top]].u;
    			}
    			int &i = cur[u];//引用类型
    			for(; i != -1; i = edge[i].next){
    				int v = edge[i].v;
    				if(edge[i].cap && lev[v] == lev[u] + 1){
    					break;
    				}
    			}
    			if(i != -1){
    				s[top++] = i;
    				u = edge[i].v;
    			}else{
    				if(!top){
    					break;
    				}
    				lev[u] = -1;
    				u = edge[s[--top]].u;
    			}
    		}
    	}
    	return ans;
    }
    
    
    std::vector<int> v[N];
    int h[N];
    int main(){
    	int n, m, k;
    	while(cin >> n >> m >> k){
    		int st = 0;
    		for(int i = 1; i <= n + 2; i++){
    			fa[i] = i;
    		}
    
    		for(int i = 1; i <= m; i++){
    			v[i].clear();
    			cin>>h[i];
    			int x;
    			cin >> x;
    
    			for(int j = 0; j < x; j++){
    				int tp;
    				cin >> tp;
    				if(tp == 0){
    					tp = n + 1;
    				}else if(tp == -1){
    					tp = n + 2;
    				}
    				v[i].push_back(tp);
    				if(j){
    					Union(v[i][j - 1], v[i][j]);
    				}
    			}
    			if(h[i] == 0){
    				i--;
    				m--;
    			}
    		}
    		if((m == 0 ) || (Find(n + 1) != Find(n + 2))){
    			printf("0
    ");
    			continue;
    		}
    
    		for(int d = 1; ; d++){
    			init();
    			add(st, n + 1, k);
    
    			for(int i = 1; i <= d; i++){
    				for(int j = 1; j <= n + 2; j++){
    					add((n + 2) * (i - 1) + j, (n + 2) * i + j, INF);
    				}
    				for(int j = 1; j <= m; j++){
    					int a = v[j][(i - 1) % v[j].size()];
    					int b = v[j][i % v[j].size()];
    					a = (n + 2) * (i - 1) + a;
    					b = (n + 2) * i + b;
    					add(a, b, h[j]);
    				}
    			}
    			int ans = dinic(st, (n + 2) * (d + 1), (n + 2) * (d + 1) + 1);
    			
    			if(ans == k){
    				printf("%d
    ", d);
    				break;
    			}
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Python学习(18)——函数
    Python学习(17)——推导式
    labview隐藏任务栏
    labview下载地址
    labview出现系统998错误
    油猴使用指南
    无法执行该VI,必须使用LabVIEW完整版开发系统才可以解决该错误
    修改远程桌面连接默认端口
    labview使用了报表模块,在生成exe时需要添加以下内容,否则打包后不能开启excel功能
    腾讯通二次开发接口
  • 原文地址:https://www.cnblogs.com/IMGavin/p/6387415.html
Copyright © 2011-2022 走看看