• [AHOI2014]支线剧情(有上下界的网络流)


    题目要求即为每条边至少经过一次,那么就想到有下界网络流(上界为正无穷),每条边的流量就代表经过了几次。建立一个源点和汇点,从源点连向 (1) 一条下界为 (0) 的边,从每个点连向汇点一条下界为 (0) 的边,应为还要求时间最短所以是上下界最小费用流。套模板即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=0x3f3f3f3f;
    template<typename T>void read(T &x){
     T flag=1;
     char ch=getchar();
     for(;'0'>ch||ch>'9';ch=getchar()){
      if(ch=='-')flag=-1;
     }
     for(x=0;'0'<=ch&&ch<='9';ch=getchar()){
      x=x*10+ch-'0';
     }
    }
    struct node{
     int pre,to,val,cost;
    }edge[100005];
    int head[100005],tot=1;
    int s, t;
    int S,T;
    int n;
    int dis[100005];
    bool vis[100005];
    int pre[100005], incf[100005];
    bool spfa() {
    	queue<int> q;
    	memset(dis, 0x3f, sizeof(dis));
    	memset(vis, 0, sizeof(vis));
    	dis[s] = 0;
    	vis[s] = 1;
    	q.push(s);
    	incf[s] = inf;
    	while (!q.empty()) {
    		int x = q.front(); q.pop();
    		for (int i = head[x]; i; i = edge[i].pre) {
    			if (!edge[i].val) continue;
    			int y = edge[i].to;
    			if (dis[y] > dis[x] + edge[i].cost) {
    				dis[y] = dis[x] + edge[i].cost;
    				incf[y] = min(incf[x], edge[i].val);
    				pre[y] = i;
    				if (!vis[y]) {
    					vis[y] = 1;
    					q.push(y);
    				}
    			}
    		}
    		vis[x] = 0;
    	}
    	if (dis[t] < 0x3f3f3f3f) return true;
    	return false;
    }
    int max_flow, ans;
    void update() {
    	int x = t;
    	while (x != s) {
    		int i = pre[x];
    		edge[i].val -= incf[t];
    		edge[i ^ 1].val += incf[t];
    		x = edge[i ^ 1].to;
    	}
    	max_flow += incf[t];
    	ans += dis[t] * incf[t];
    }
    void add_edge(int u,int v,int l,int w){
     edge[++tot]=node{head[u],v,l,w};
     head[u]=tot;
     edge[++tot]=node{head[v],u,0,-w};
     head[v]=tot;
    }
    struct node2{
     int x,y,low,lim,cost;
    }edge2[10005];
    int tot2;
    void add_edge2(int u,int v,int l,int r,int w) {
     edge2[++tot2]=node2{u,v,l,r,w};
    }
    int flow[10005];
    int main(){
     S=0,T=n+1;
     read(n);
     add_edge2(0,S,0,inf,0);
     for(int i=1,k;i<=n;i++){
      read(k);
      for(int j=1,v,w;j<=k;j++){
       read(v);read(w);
       add_edge2(i,v,1,inf,w);
      }
      add_edge2(i,T,0,inf,0);
     }
     add_edge2(T, S, 0, inf, 0);
     s=n+2,t=n+3;
     for (int i = 1; i <= tot2; i++) {
     	int x=edge2[i].x,y = edge2[i].y;
     	flow[x]-=edge2[i].low;
     	flow[y]+=edge2[i].low;
     	edge2[i].lim-=edge2[i].low;
     	ans+=edge2[i].low * edge2[i].cost;
     	add_edge(x, y, edge2[i].lim, edge2[i].cost);
     }
     for (int i = 0; i <= n+1; i++) {
     	if (flow[i] > 0) {
     		add_edge(s, i, flow[i], 0);
    	 } else if (flow[i] < 0) {
    	 	add_edge(i, t, -flow[i], 0);
    	 }
     }
     while (spfa()) {
     	update();
     }
     printf("%d
    ", ans);
     return 0;
    }
    
  • 相关阅读:
    MySQL实用基本操作
    数组经典例题
    Java基础之流程控制
    Java基础之数组详解
    java基础语法(三大基础)
    golang map转json
    go get 无反应、访问github.com速度慢、没反应问题的解决方案
    微信公众平台,微信网页授权,redirect_uri参数错误,解决方法!
    通过 nginx 访问 golang web
    golang 报错信息及解决方法--采坑之路,学习使我快乐
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14333272.html
Copyright © 2020-2023  润新知