【2017杭二联考】 图的有向环

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 }

 

 

posted @ 2017-08-21 23:45  nfy_algorithm  阅读(379)  评论(0编辑  收藏  举报