生活随笔
收集整理的這篇文章主要介紹了
洛谷 [SDOI2009]晨跑
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
Elaxia最近迷戀上了空手道,他為自己設定了一套健身計劃,比如俯臥撐、仰臥起坐等 等,不過到目前為止,他堅持下來的只有晨跑。 現在給出一張學校附近的地圖,這張地圖中包含N個十字路口和M條街道,Elaxia只能從 一個十字路口跑向另外一個十字路口,街道之間只在十字路口處相交。Elaxia每天從寢室出發 跑到學校,保證寢室編號為1,學校編號為N。 Elaxia的晨跑計劃是按周期(包含若干天)進行的,由于他不喜歡走重復的路線,所以 在一個周期內,每天的晨跑路線都不會相交(在十字路口處),寢室和學校不算十字路 口。Elaxia耐力不太好,他希望在一個周期內跑的路程盡量短,但是又希望訓練周期包含的天 數盡量長。 除了練空手道,Elaxia其他時間都花在了學習和找MM上面,所有他想請你幫忙為他設計 一套滿足他要求的晨跑計劃。
存在1\rightarrow n1→n的邊存在。這種情況下,這條邊只能走一次。
輸入輸出格式
輸入格式:
第一行:兩個數N,M。表示十字路口數和街道數。 接下來M行,每行3個數a,b,c,表示路口a和路口b之間有條長度為c的街道(單向)。
輸出格式:
兩個數,第一個數為最長周期的天數,第二個數為滿足最長天數的條件下最短的路程長 度。
輸入輸出樣例
輸入樣例#1:
7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1
輸出樣例#1:
2 11
說明
對于30%的數據,N ≤ 20,M ≤ 120。
對于100%的數據,N ≤ 200,M ≤ 20000。
.
.
.
.
.
分析
每個點只能走一次,可以想到拆點的思想——把一個點拆成兩個中間連一條流量為1的邊,這樣在流過一次以后流量變為0,這個點就只能用一次了。
對于除了S和T的點,拆點的連邊容量為1,費用為0; 其他的邊的容量定為1,費用為路徑長度,跑出最大流即為最大天數,最小費用和為最短路徑;
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;int n,m,cnt=0,st,ed;
int last[1000]; queue<int> l;struct nodx
{int d,v,f;
}a[1000];
struct nodb
{int x,y,c,d,f,next;
}b[1000000]; void add(int x,int y,int c,int d)
{ b[++cnt].x=x;b[cnt].y=y;b[cnt].c=c;b[cnt].d=d;b[cnt].f=cnt+1;b[cnt].next=last[x];last[x]=cnt; b[++cnt].x=y;b[cnt].y=x;b[cnt].c=0;b[cnt].d=-d;b[cnt].f=cnt-1;b[cnt].next=last[y];last[y]=cnt;
} bool spfa()
{ for (int i=1;i<=ed;i++) { a[i].v=0; a[i].d=2147483647; } a[st].d=0;a[st].v=1; l.push(st);while (!l.empty()) { int x=l.front();l.pop();for (int i=last[x];i>0;i=b[i].next) { int y=b[i].y; if (a[y].d>a[x].d+b[i].d&&b[i].c>0) { a[y].d=a[x].d+b[i].d; a[y].f=i;if (a[y].v==0) { a[y].v=1;l.push(y);} } } a[x].v=0; } int x=ed; while (x!=st) { int i=a[x].f; b[i].c-=1; b[b[i].f].c+=1; x=b[i].x; } if (a[ed].d<2147483647) return true; return false;
} int main()
{ scanf("%d%d",&n,&m); memset(last,0,sizeof(last));st=1;ed=n*2; add(1,n+1,2147483647,0);add(n,n*2,2147483647,0);for (int i=2;i<n;i++) add(i,i+n,1,0);for (int i=1;i<=m;i++){ int x,y,c; scanf("%d%d%d",&x,&y,&c); add(x+n,y,1,c); } int ans=0,sum=0; while (spfa()){ ans++;sum+=a[ed].d;} printf("%d %d",ans,sum); return 0;
}
轉載于:https://www.cnblogs.com/YYC-0304/p/11094941.html
總結
以上是生活随笔為你收集整理的洛谷 [SDOI2009]晨跑的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。