LuoguP2754 [CTSC1999]家园(分层图,最大流)
題目背景
none!
題目描述
由于人類對自然資源的消耗,人們意識到大約在 2300 年之后,地球就不能再居住了。于是在月球上建立了新的綠地,以便在需要時移民。令人意想不到的是,2177 年冬由于未知的原因,地球環境發生了連鎖崩潰,人類必須在最短的時間內遷往月球。
現有 n 個太空站位于地球與月球之間,且有 m 艘公共交通太空船在其間來回穿梭。每個太空站可容納無限多的人,而每艘太空船 i 只可容納 H[i]個人。每艘太空船將周期性地停靠一系列的太空站,例如:(1,3,4)表示該太空船將周期性地停靠太空站 134134134…。每一艘太空船從一個太空站駛往任一太空站耗時均為 1。人們只能在太空船停靠太空站(或月球、地球)時上、下船。
初始時所有人全在地球上,太空船全在初始站。試設計一個算法,找出讓所有人盡快地全部轉移到月球上的運輸方案。
對于給定的太空船的信息,找到讓所有人盡快地全部轉移到月球上的運輸方案。
輸入輸出格式
輸入格式:
第 1 行有 3 個正整數 n(太空站個數),m(太空船個數)和 k(需要運送的地球上的人的個數)。其中 n<=13 m<=20, 1<=k<=50。
接下來的 m 行給出太空船的信息。第 i+1 行說明太空船 pi。第 1 個數表示 pi 可容納的人數 Hpi;第 2 個數表示 pi 一個周期停靠的太空站個數 r,1<=r<=n+2;隨后 r 個數是停靠的太空站的編號(Si1,Si2,…,Sir),地球用 0 表示,月球用-1 表示。
時刻 0 時,所有太空船都在初始站,然后開始運行。在時刻 1,2,3…等正點時刻各艘太空船停靠相應的太空站。人只有在 0,1,2…等正點時刻才能上下太空船。
輸出格式:
程序運行結束時,將全部人員安全轉移所需的時間輸出。如果問題
無解,則輸出 0。
解題思路:
假如說告訴你多少天,問轉移人口,那是不是會好一些,
按時間分層,不同層相同點間按照時間方向建$inf$的邊,
跑一邊最大流,源點是0時刻的地球,匯點是T時刻的月球。
最大流就是人口。
所以枚舉判斷好了。
代碼:
1 #include<queue> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 const int oo=0x3f3f3f3f; 7 struct pnt{ 8 int hd; 9 int lyr; 10 int now; 11 }p[10000]; 12 struct ent{ 13 int twd; 14 int lst; 15 int vls; 16 }e[1000000]; 17 int cnt; 18 int n,m,k; 19 int s,t; 20 int size; 21 int H[1000]; 22 int fa[1000]; 23 std::queue<int>Q; 24 std::vector<int>st[1000]; 25 void ade(int f,int t,int v) 26 { 27 cnt++; 28 e[cnt].twd=t; 29 e[cnt].vls=v; 30 e[cnt].lst=p[f].hd; 31 p[f].hd=cnt; 32 return ; 33 } 34 bool Bfs(void) 35 { 36 while(!Q.empty()) 37 Q.pop(); 38 for(int i=1;i<=size;i++) 39 p[i].lyr=0; 40 p[s].lyr=1; 41 Q.push(s); 42 while(!Q.empty()) 43 { 44 int x=Q.front(); 45 Q.pop(); 46 for(int i=p[x].hd;i;i=e[i].lst) 47 { 48 int to=e[i].twd; 49 if(p[to].lyr==0&&e[i].vls>0) 50 { 51 p[to].lyr=p[x].lyr+1; 52 if(to==t) 53 return true; 54 Q.push(to); 55 } 56 } 57 } 58 return false; 59 } 60 int Dfs(int x,int fll) 61 { 62 if(x==t) 63 return fll; 64 for(int& i=p[x].now;i;i=e[i].lst) 65 { 66 int to=e[i].twd; 67 if(p[to].lyr==p[x].lyr+1&&e[i].vls>0) 68 { 69 int ans=Dfs(to,std::min(fll,e[i].vls)); 70 if(ans>0) 71 { 72 e[i].vls-=ans; 73 e[((i-1)^1)+1].vls+=ans; 74 return ans; 75 } 76 } 77 } 78 return 0; 79 } 80 int Dinic(void) 81 { 82 int ans=0; 83 while(Bfs()) 84 { 85 for(int i=1;i<=size;i++) 86 p[i].now=p[i].hd; 87 int dlt; 88 while(dlt=Dfs(s,oo)) 89 ans+=dlt; 90 } 91 return ans; 92 } 93 int finf(int x) 94 { 95 return fa[x]==x?x:fa[x]=finf(fa[x]); 96 } 97 int main() 98 { 99 // freopen("a.in","r",stdin); 100 scanf("%d%d%d",&n,&m,&k); 101 for(int i=1;i<=n+m+2;i++)fa[i]=i; 102 for(int i=1;i<=m;i++) 103 { 104 scanf("%d",&H[i]); 105 int tmp; 106 scanf("%d",&tmp); 107 for(int j=1;j<=tmp;j++) 108 { 109 int tl; 110 scanf("%d",&tl); 111 if(tl==0)tl=n+1; 112 if(tl==-1)tl=n+2; 113 st[i].push_back(tl); 114 int f1=finf(tl); 115 int f2=finf(n+2+i); 116 if(f1!=f2) 117 fa[f1]=f2; 118 } 119 } 120 if(finf(n+1)!=finf(n+2)) 121 { 122 printf("%d\n",0); 123 return 0; 124 } 125 s=n+1; 126 int N; 127 int popu=0; 128 for(N=0;;N++) 129 { 130 if(N) 131 { 132 for(int i=1;i<=n+m+2;i++) 133 { 134 ade((N-1)*(n+m+2)+i,N*(n+m+2)+i,oo); 135 ade(N*(n+m+2)+i,(N-1)*(n+m+2)+i,0); 136 } 137 } 138 size=(N+1)*(n+m+2); 139 t=N*(n+m+2)+n+2; 140 for(int i=1;i<=m;i++) 141 { 142 int tp=st[i][N%st[i].size()]; 143 if(tp!=n+1) 144 { 145 ade(N*(n+m+2)+n+2+i,N*(n+m+2)+tp,H[i]); 146 ade(N*(n+m+2)+tp,N*(n+m+2)+n+2+i,0); 147 } 148 if(tp!=n+2) 149 { 150 ade(N*(n+m+2)+tp,N*(n+m+2)+n+2+i,H[i]); 151 ade(N*(n+m+2)+n+2+i,N*(n+m+2)+tp,0); 152 } 153 } 154 popu+=Dinic(); 155 if(popu<k);else break; 156 } 157 printf("%d\n",N); 158 return 0; 159 }?
轉載于:https://www.cnblogs.com/blog-Dr-J/p/10205634.html
總結
以上是生活随笔為你收集整理的LuoguP2754 [CTSC1999]家园(分层图,最大流)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【UOJ34】—多项式乘法(FFT)
- 下一篇: 正则RegExc