zoukankan      html  css  js  c++  java
  • bzoj 2163: 复杂的大门

    2163: 复杂的大门

    Time Limit: 20 Sec  Memory Limit: 259 MB
    Submit: 418  Solved: 259
    [Submit][Status][Discuss]

    Description

    你去找某bm玩,到了门口才发现要打开他家的大门不是一件容易的事……
    他家的大门外有n个站台,用1到n的正整数编号。你需要对每个站台访问一定次数以后大门才能开启。站台之间有m个单向的传送门,通过传送门到达另一个站台不需要花费任何代价。而如果不通过传送门,你就需要乘坐公共汽车,并花费1单位的钱。值得庆幸的是,任意两个站台之间都有公共汽车直达。
    现在给你每个站台必须访问的次数Fi,对于站台i,你必须恰好访问Fi次(不能超过)。
    我们用u、v、w三个参数描述一个传送门,表示从站台u到站台v有一个最多可以使用w次的传送门(不一定要使用w次)。值得注意的是,对于任意一对传送门(u1,v1)和(u2,v2),如果有u1<u2,则有v1≤v2;如果有v1<v2,则有u1≤u2;且u1=u2和v1=v2不同时成立。
    你可以从任意的站台开始,从任意的站台结束。出发去开始的站台需要花费1单位的钱。你需要求出打开大门最少需要花费多少单位的钱。

    Input

    第一行包含两个正整数n、m,意义见题目描述。第二行包含n个正整数,第i个数表示Fi。接下来有m行,每行有三个正整数u、v、w,表示从u到v有一个可以使用w次的传送门。

    Output

    输出一行一个整数,表示打开大门最少花费的钱数。

    Sample Input

    4 3
    5 5 5 5
    1 2 1
    3 2 1
    3 4 1

    Sample Output

    17

    HINT

    有20%的数据满足n≤10,m≤50;对于所有的w、Fi,满足1≤w,Fi≤10。有50%的数据满足n≤1000,m≤10000。100%的数据满足1≤n≤10000,1≤m≤100000;对于所有的u、v,满足1≤u,v≤n,u≠v;对于所有的w、Fi,满足1≤w,Fi≤50000。以上的每类数据中都存在50%的数据满足对于所有的w、Fi,有w=Fi=1。

        貌似这就是最小路径覆盖的一个点可以被经过多次的版本啊。

        最小路径覆盖是要求选尽量少的路径,使得每个点都恰好在一条路径上(也就是路径之间没有交点)。。。。

        那么本题就是 要求选尽量少的路径,使得所有点i都满足 i 恰好在 F[i] 条路径上。。。。。

        做法是一样的嘛。。。左边一排出点,右边一排入点,因为题目中保证了没有环(那个边的关系就是这个意思),然后Fi的和减去最大流就是答案(也就是会有多少路径起点)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define pb push_back
    const int maxn=20005;
    vector<int> g[maxn];
    struct lines{
    	int to,flow,cap;
    }l[maxn*79];
    int S,T,t=-1,d[maxn],cur[maxn];
    bool v[maxn];
    
    inline void add(int from,int to,int cap){
    	l[++t]=(lines){to,0,cap},g[from].pb(t);
    	l[++t]=(lines){from,0,0},g[to].pb(t);
    }
    
    inline bool BFS(){
    	memset(v,0,sizeof(v)),v[S]=1,d[S]=0;
    	queue<int> q; q.push(S);
    	int x; lines e;
    
    	while(!q.empty()){
    		x=q.front(),q.pop();
    		for(int i=g[x].size()-1;i>=0;i--){
    			e=l[g[x][i]];
    			if(e.flow<e.cap&&!v[e.to]) v[e.to]=1,d[e.to]=d[x]+1,q.push(e.to);
    		}
    	}
    	
    	return v[T];
    }
    
    int dfs(int x,int A){
    	if(x==T||!A) return A;
    	int flow=0,f,sz=g[x].size();
    	
    	for(int &i=cur[x];i<sz;i++){
    		lines &e=l[g[x][i]];
    		if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(A,e.cap-e.flow)))){
    			A-=f,flow+=f;
    			e.flow+=f,l[g[x][i]^1].flow-=f;
    			if(!A) break;
    		}
    	}
    	
    	return flow;
    }
    
    inline int max_flow(){
    	int an=0;
    
    	while(BFS()){
    		memset(cur,0,sizeof(cur));
    		an+=dfs(S,1<<30);
    	}
    	
    	return an;
    }
    
    int n,now,tot,m;
    
    int main(){
    	int uu,vv,ww;
    	scanf("%d%d",&n,&m),S=0,T=(n<<1)|1;
    	for(int i=1;i<=n;i++) scanf("%d",&now),add(S,i,now),add(i+n,T,now),tot+=now;
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&uu,&vv,&ww),add(uu,vv+n,ww);
    	
    	printf("%d
    ",tot-max_flow());
    	return 0;
    }
    
  • 相关阅读:
    PE格式详细讲解2 系统篇02|解密系列
    结构体与共用体06 零基础入门学习C语言58
    PE格式详细讲解3 系统篇03|解密系列
    我的学习路
    结构体与共用体07 零基础入门学习C语言59
    PE格式详细讲解2 系统篇02|解密系列
    PE格式详细讲解3 系统篇03|解密系列
    Windows Azure 社区新闻综述(#61 版)
    Django 现可在 Windows Azure 上使用
    Windows Azure Active Directory正式发布:已提供了超过 2650 亿个身份验证和服务了290万个组织!
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9111738.html
Copyright © 2011-2022 走看看