P2469 [SDOI2010]星际竞速
生活随笔
收集整理的這篇文章主要介紹了
P2469 [SDOI2010]星际竞速
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P2469 [SDOI2010]星際競速
題意:
有n個點,m個邊,邊是單向邊(只能從小編號點到大編號點),你也可以花費ai直接到達點i。問將1~n所有點都經過一邊最小費用是多少?
題解:
最小費用最大流,網絡流的題都是板子題,那就難在如何建邊
先說結論:
拆點i為ixi_xix?和iyi_yiy?
回顧最小路徑覆蓋問題:
原圖用n條路徑覆蓋,每條邊只經過每個節點。
現在盡量合并更多的路徑(即將兩個路徑通過一條邊首尾相連),可以直到,每合并兩條路徑,圖中路徑的覆蓋數就會減1.
最小路徑覆蓋的解決方法就是將n個點拆成iii和i′i'i′,然后源點向所有點i連一條容量為1的邊,再由所有的i′i'i′點向匯點連一條容量為1的邊,對于每條邊u->v,由u向v′v'v′連一條容量為1的邊,跑一邊最大流,n減去最大流就是最小路徑覆蓋
本題就是運行這種思想
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define ll long long #define inf 50000000 #define re register using namespace std; struct po {int from,to,dis,nxt,w; }edge[250001]; int head[250001],cur[1000001],dep[60001],n,m,s,t,u,num=-1,x,y,l,tot,sum,k,fa[10001]; int dis[5001],vis[5001],xb[5001],flow[5001]; inline int read() {int x=0,c=1;char ch=' ';while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();while(ch=='-')c*=-1,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();return x*c; } inline void add_edge(int from,int to,int w,int dis) {edge[++num].nxt=head[from];edge[num].from=from;edge[num].to=to;edge[num].w=w;edge[num].dis=dis;head[from]=num; } inline void add(int from,int to,int w,int dis) {add_edge(from,to,w,dis);add_edge(to,from,0,-dis); } inline bool spfa() {memset(dis,100,sizeof(dis));memset(vis,0,sizeof(vis));queue<int> q;while(!q.empty())q.pop();for(re int i=1;i<=n;i++){fa[i]=-1;}vis[s]=1;dis[s]=0;fa[s]=0;flow[s]=inf;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(re int i=head[u];i!=-1;i=edge[i].nxt){int v=edge[i].to;if(edge[i].w>0&&dis[v]>dis[u]+edge[i].dis){dis[v]=dis[u]+edge[i].dis;fa[v]=u;xb[v]=i;flow[v]=min(flow[u],edge[i].w);if(!vis[v]){vis[v]=1,q.push(v);}}}}return dis[t]<inf; } inline void max_flow() {while(spfa()){int k=t;while(k!=s){edge[xb[k]].w-=flow[t];edge[xb[k]^1].w+=flow[t];k=fa[k];}tot+=flow[t];sum+=flow[t]*dis[t];} } int main() {memset(head,-1,sizeof(head));int d;n=read();m=read();s=0;t=2*n+1;for(int i=1;i<=n;i++){int x;scanf("%d",&x);add(s,i,1,0);add(s,i+n,1,x);add(i+n,t,1,0);}for(re int i=1;i<=m;i++){x=read();y=read();l=1;d=read();if(x>y)swap(x,y);add(x,n+y,l,d);}max_flow();cout<<sum; }總結
以上是生活随笔為你收集整理的P2469 [SDOI2010]星际竞速的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 佩兰的功效与作用、禁忌和食用方法
- 下一篇: P2467 [SDOI2010]地精部落