[CTSC1999]家園(網絡流)
題目描述
由於人類對自然資源的消耗,人們意識到大約在 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。
輸入輸出樣例
輸入樣例#1: 復制2 2 1
1 3 0 1 2
1 3 1 2 -1
輸出樣例#1: 復制
5
說明
none!
又發現了一道神題;
網上說這題綜合了信息學和物理上的狹義相對論
不愧是ctsc的題啊
本題的建模是真的難想啊
由於數據範圍較小,可以對每一天進行考慮。
考慮每一天時,對每個太空站都建個新的點代表當前天的太空站,地球和月球也新建。
從源點向地球連容量為inf的邊,月球向匯點連容量為inf的邊。
然後每個太空站可以從上一天留下inf個人,所以從前一天連一條容量為inf的邊。
考慮每個太空船,可以從前一天所在的點轉移hi個人過來,所以連一條容量為hi的邊。
然後跑最大流,最大流為當前天可送達的人數
建完邊直接從殘量網絡繼續跑就行了
無解可以用並查集判,也可以判如果天數大於500,即一個一個的送,經過所有點都送不完的話,就無解。
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 inline void read(int &x) {
5 x=0;int f=1;char ch=getchar();
6 for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-f;
7 for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
8 }
9
10 inline void print(int x) {
11 if(x<0) putchar(‘-‘),x=-x;
12 if(!x) return ;print(x/10),putchar((x%10)^48);
13 }
14 inline void write(int x) {if(!x) putchar(‘0‘);else print(x);putchar(‘\n‘);}
15
16 #define maxn 1000050
17
18 int n,m,s,t,max_flow,tot=1,k;
19 int head[maxn],dis[maxn],vis[maxn],a[200][200],num[200],v[200];
20 struct edge{int to,nxt,w;}e[maxn<<1];
21
22 void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
23 void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);}
24
25 int bfs() {
26 memset(vis,0,sizeof vis);
27 memset(dis,63,sizeof dis);//write(dis[0]);
28 queue<int > q;q.push(s);vis[s]=1;dis[s]=0;
29 while(!q.empty()) {
30 int now=q.front();q.pop();vis[now]=0;
31 for(int i=head[now];i;i=e[i].nxt)
32 if(e[i].w>0&&dis[e[i].to]>dis[now]+1) {
33 dis[e[i].to]=dis[now]+1;
34 if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
35 }
36 }return dis[t]<1e9;
37 }
38
39 int dfs(int u,int flow) {
40 if(u==t) return flow;
41 for(int i=head[u];i;i=e[i].nxt)
42 if(e[i].w>0&&dis[e[i].to]==dis[u]+1) {
43 int f=dfs(e[i].to,min(flow,e[i].w));
44 if(f>0) {e[i].w-=f,e[i^1].w+=f;return f;}
45 }
46 dis[u]=-1;return 0;
47 }
48
49 int dinic() {
50 max_flow=0;
51 while(bfs()) {
52 int flow;
53 while((flow=dfs(s,1e9))) max_flow+=flow;
54 }return max_flow;
55 }
56
57 int main() {
58 s=0,t=1e4;
59 read(n),read(m),read(k);
60 for(int i=1;i<=m;i++) {
61 read(v[i]),read(num[i]);
62 for(int j=0;j<num[i];j++) read(a[i][j]),a[i][j]+=2;
63 }
64 int ans=1,res=0;
65 ins(s,0*(n+2)+2,1e9);
66 ins(0*(n+2)+1,t,1e9);
67 while(1) {
68
69 ins(s,ans*(n+2)+2,1e9);
70 ins(ans*(n+2)+1,t,1e9);
71 if(ans) {
72 for(int i=1;i<=n;i++) ins((ans-1)*(n+2)+i+2,ans*(n+2)+i+2,1e9);
73 for(int i=1;i<=m;i++) ins((ans-1)*(n+2)+a[i][(ans-1)%num[i]],ans*(n+2)+a[i][ans%num[i]],v[i]);
74 }
75
76 res+=dinic();if(res>=k) return write(ans),0;
77 ans++;if(ans==500) return puts("0"),0;
78 }
79 return 0;
80 }
[CTSC1999]家園(網絡流)