• ●BOZJ 1927 [Sdoi2010]星际竞速


    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1927

    题解:

    显然是个DAG
    建图和有向图最小路径覆盖的建图有些相似。
     
    都是拆点为 u u'分别表示出点和入点。
    也都要保证每个点最多有一个出度和一个入度。

    但因为带权,要求最小花费,切要满足每个点都去一次,既要满足流量,所以采用最小费用最大流。
    S -> u :(1,0) 因为每个点都会到达,所以都可以有一个出度(可以从改点流出一个流量)。
    S -> u':(1,a[u]) 传送到达 u点,提供一个入度方式
    u -> v':(1,w) u的出度对应 v的入度
    u'-> T :(1,0) 流向汇点,表示改点到达过。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 2000
    #define MAXM 50000
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ll long long
    using namespace std;
    struct Edge{
    	ll to[MAXM],cap[MAXM],cot[MAXM],nxt[MAXM],head[MAXN],ent;
    	void Init(){ent=2;}
    	void Adde(ll u,ll v,ll w,ll c){
    		to[ent]=v; cap[ent]=w; cot[ent]=c; nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; cap[ent]=0; cot[ent]=-c;nxt[ent]=head[v]; head[v]=ent++;
    	}
    	ll Next(ll i,bool type){
    		return type?head[i]:nxt[i];
    	}
    }E;
    bool vis[MAXN];
    ll cur[MAXN],dis[MAXN];
    ll N,M,S,T;
    ll idx(ll i,ll k){
    	return i+k*N;
    }
    bool spfa(){
    	static bool inq[MAXN];
    	memset(inq,0,sizeof(inq));
    	memset(dis,0x3f,sizeof(dis)); ll u,v;
    	queue<ll> q; dis[T]=0; inq[T]=1; q.push(T);
    	while(!q.empty()){
    		u=q.front(); q.pop(); inq[u]=0;
    		for(ll i=E.Next(u,1);i;i=E.Next(i,0)){
    			v=E.to[i];
    			if(!E.cap[i^1]||dis[v]<=dis[u]+E.cot[i^1]) continue;
    			dis[v]=dis[u]+E.cot[i^1];
    			if(!inq[v]) q.push(v),inq[v]=1;
    		}
    	}
    	return dis[S]<INF;
    }
    ll dfs(ll u,ll reflow){
    	if(u==T||!reflow) return reflow;
    	ll flowout=0,f,v; vis[u]=1;
    	for(ll &i=cur[u];i;i=E.Next(i,0)){
    		v=E.to[i];
    		if(vis[v]||dis[v]+E.cot[i]!=dis[u]) continue;
    		f=dfs(v,min(reflow,E.cap[i]));
    		flowout+=f; E.cap[i^1]+=f;
    		reflow-=f;	E.cap[i]-=f;
    		if(!reflow) break;
    	}
    	if(!flowout) dis[u]=INF;
    	return flowout;
    }
    ll Dinic(){
    	ll cost=0;
    	while(spfa()){
    		memcpy(cur,E.head,sizeof(E.head));
    		memset(vis,0,sizeof(vis));
    		cost+=dfs(S,INF)*dis[S];
    	}
    	return cost;
    }
    int main()//开long long 
    {
    	E.Init();
    	scanf("%lld%lld",&N,&M);
    	S=N*2+1; T=N*2+2;
    	for(ll i=1,w;i<=N;i++){//传送到达 i点。
    		scanf("%lld",&w);
    		E.Adde(S,idx(i,1),1,w);
    	}
    	for(ll i=1,u,v,w;i<=M;i++){
    		scanf("%lld%lld%lld",&u,&v,&w);
    		if(u>v) swap(u,v);
    		E.Adde(idx(u,0),idx(v,1),1,w);//u的出度对应 v的入度。
    	}
    	for(ll i=1;i<=N;i++){
    		E.Adde(S,idx(i,0),1,0);//因为每个点都会到达,所以都可以提供一个出度。 
    		E.Adde(idx(i,1),T,1,0);//流向汇点,表示改点到达。 
    	}
    	ll cost=Dinic();
    	printf("%lld",cost);
    	return 0;
    }
    

  • 相关阅读:
    [leetcode] 135. Candy (hard)
    [leetcode] 134. Gas Station (medium)
    [OpenGL] 绘制并且判断凹凸多边形、自相交多边形。
    [leetcode] 45. Jump Game II(hard)
    [leetcode] 55. Jump Game (Medium)
    [leetcode] 392. Is Subsequence (Medium)
    [leetcode] 147. Insertion Sort List (Medium)
    [leetcode]914. X of a Kind in a Deck of Cards (easy)
    [leetcode] 234. Palindrome Linked List (easy)
    [leetcode] 290. Word Pattern (easy)
  • 原文地址:https://www.cnblogs.com/zj75211/p/7931384.html
Copyright © 2020-2023  润新知