1. 程式人生 > >【2017杭二聯考】 圖的有向環

【2017杭二聯考】 圖的有向環

tor gist fin lin def clu pro script space

P2555 - 【2017杭二聯考】圖的有向環

Description

題目背景:
幻想鄉的亡靈公主,西行寺幽幽子,在幻想鄉很受歡迎,經常有妖怪來拜訪她,但是幽 幽子並不喜歡被打擾,她希望從白玉樓出發,散步之後再回到白玉樓,同時路上遇到的妖怪 越少越好(有趣的是道路兩邊的妖怪數量並不相同,分別從兩個方向經過同一條道路遇到的 妖怪數量是不同的)。當然,作為冥界的公主,她是不會重復經過同一條道路的。

問題描述:
給定一個有 n 個點 m 條無向邊的圖,每條無向邊最多只能經過一次。
對於邊(ui, vi), 從 ui 到 vi 的代價為 ai,從 vi 到 ui 的代價為 bi,其中 ai 和 bi 不一定相等。 求一個包 含 1 號點的有向環,使得環上代價之和最小。(保證圖中沒有重邊和自環。)

Input

第一行兩個個正整數 n,m,點數和邊數。
接下來 m 行,每行四個正整數,ui,vi,ai,bi。
從 ui 到 vi 的代價為 ai,從 vi 到 ui 的代價為 bi 。

Output

輸出一行,一個整數,如果有解輸出最小代價,否則輸出‘‘-1‘‘(不含引號)。

Sample Input

3 3
1 2 4 3
2 3 4 2
1 3 1 1

Sample Output

6

Hint

數據範圍:
對於前 15% 的數據,3 <= n <= 20, 3 <= m <= 20
對於前 30% 的數據,3 <= n <= 150, 3 <= m <= 2500
對於前 70% 的數據,3 <= n <= 5000, 3 <= m <= 10^4
對於 100% 的數據, 3 <= n <= 30000 , 3 <= m <= 10^5 , 1<=ui, vi <= n,1 <= ai, bi <= 10^4。
保證圖中沒有重邊,即不存在 i <> j,使得 ui = uj,vi = vj。
保證圖中沒有自環,即 ui <> vi。

Source

圖論,最短路

枚舉與一號點相連的每一條邊,再跑SPFA,min(枚舉的邊的長度+dis[1])即為答案,但是要註意剪枝和優化.
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<stack>
 9
#include<queue> 10 #include<map> 11 #define RG register 12 #define IL inline 13 #define pi acos(-1.0) 14 #define ll long long 15 using namespace std; 16 struct edge{ 17 int first,nxt,to,w; 18 }; 19 edge a[200050]; 20 int n,m,num,minn; 21 int f[200050],dis[100050]; 22 bool pan[100050]; 23 void add(int l,int r,int w){ 24 a[++num].to=r; 25 a[num].w=w; 26 a[num].nxt=a[l].first; 27 a[l].first=num; 28 } 29 inline void spfa(int S,int w){ 30 for(RG int i=1;i<=n;i++) dis[i]=999999999; 31 memset(pan,true,sizeof(pan)); 32 queue <int> s; 33 s.push(S); 34 dis[S]=w; 35 while(!s.empty()){ 36 int u=s.front(); 37 s.pop(); 38 pan[u]=true; 39 if(dis[u]>=minn) continue; 40 if(u==1) {minn=min(minn,dis[u]);continue;} 41 for(int i=a[u].first;i;i=a[i].nxt){ 42 if(f[i]) continue; 43 int v=a[i].to; 44 if(dis[u]+a[i].w<dis[v]){ 45 dis[v]=dis[u]+a[i].w; 46 if(pan[v]){ 47 pan[v]=false; 48 s.push(v); 49 } 50 } 51 } 52 } 53 } 54 int main() { 55 scanf("%d%d",&n,&m); 56 for(int i=1;i<=m;i++){ 57 int u,v,a,b; 58 scanf("%d%d%d%d",&u,&v,&a,&b); 59 add(u,v,a),add(v,u,b); 60 } 61 minn=999999999; 62 for(int i=a[1].first;i;i=a[i].nxt){ 63 f[i]=1; 64 if(i%2==0) f[i-1]=1; 65 else f[i+1]=1; 66 spfa(a[i].to,a[i].w); 67 f[i]=0; 68 if(i%2==0) f[i-1]=0; 69 else f[i+1]=0; 70 } 71 if(minn==999999999) printf("-1"); 72 else printf("%d",minn); 73 return 0; 74 }

【2017杭二聯考】 圖的有向環