码迷,mamicode.com
首页 > 其他好文 > 详细

[Awson原创]修水渠(canal)

时间:2017-07-28 20:53:55      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:put   mat   using   inpu   stack   memset   nbsp   style   string   

Description

Awson是某国际学校信竞组的一只菜鸡。他们班主任F老师喜欢带他们去爬爬唷喽山。登顶后,Awson有了个奇怪的发现。

山腰上有N(1<=N<=100)个村庄,这些村庄可以用平面坐标(X,Y)刻画。假设要给这N个村庄供水。已知1号村庄内有一个处理水厂, 从此处可以输水给其他各个村庄。现在给出M(1<=M<=10000)种修水渠的方案,每种方案的水渠连接两个村庄U,V。由于地势等其他原 因,水的运输是单向的,即只能从U运输到V。水渠是笔直的,即水渠的长度就是U,V两村庄的欧式距离。因为Awson是一个善于发现问题、提出问题,但不 喜欢解决问题的人。所以他找到了你,烦请你设计出能够将水输送到所有村庄的方案,并且使水渠总长度最小。

Input

第1行:两个整数,N,M。

接下来N行,每行两个整数,第i行Xi,Yi,表示村庄的坐标。

再接下来M行,每行两个整数,第i行Ui,Vi,表示Ui,Vi两村庄间有一条从Ui到Vi的修水渠方案。

Output

共1行,1个整数,表示使所有机房连上网的费用最小值。

Sample Input1

4 6
0 6
4 6
0 0
7 20
1 2
1 3
2 3
3 4
3 1
3 2

Sample Output1

31.19

Sample Input2

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

Sample Output2

poor Awson

Hint

样例解释:

对于样例1:选择第1、2、4方案,长度最小,其为31.19;

对于样例2:没有方案使其连通。

数据规模:

40%的数据:1<=N<=50,1<=M<=2500;

100%的数据:1<=N<=100,1<=M<=10000,1<=X,Y<=10000,数据不保证无自环,不保证无重边、回边。

题解

朱刘算法裸题,当模板存着。

  1 #include<map>
  2 #include<queue>
  3 #include<stack>
  4 #include<vector>
  5 #include<ctime>
  6 #include<cmath>
  7 #include<cstdio>
  8 #include<string>
  9 #include<cstdlib>
 10 #include<cstring>
 11 #include<iostream>
 12 #include<algorithm>
 13  using namespace std;
 14 const int N=100;
 15 
 16 struct node
 17 {
 18     int x,y;
 19 }pos[N+5];
 20 struct tt
 21 {
 22     int u,v;
 23     double c;
 24 }edge[N*N+5];
 25 int n,m,u,v;
 26 inline double Dist(int u,int v);
 27 
 28 double in[N+5];
 29 int vis[N+5];
 30 int pre[N+5];
 31 int id[N+5],cnt;
 32 double ZLEdmons();
 33 
 34 int main()
 35 {
 36     scanf("%d%d",&n,&m);
 37     for (int i=1;i<=n;i++) scanf("%d%d",&pos[i].x,&pos[i].y);
 38     bool in[N+5]={0};
 39     for (int i=1;i<=m;i++)
 40     {
 41         scanf("%d%d",&u,&v);
 42         edge[i].v=v;
 43         edge[i].u=u;
 44         edge[i].c=Dist(u,v);
 45         in[v]=1;
 46     }
 47     for (int i=1;i<=n;i++) if (!in[i])
 48     {
 49         printf("poor Awson\n");
 50         return 0;
 51     }
 52     printf("%.2lf\n",ZLEdmons());
 53     return 0;
 54 }
 55 
 56 inline double Dist(int u,int v){return sqrt((pos[u].x-pos[v].x)*(pos[u].x-pos[v].x)+(pos[u].y-pos[v].y)*(pos[u].y-pos[v].y));}
 57 double ZLEdmons()
 58 {
 59     double ans=0;
 60     int root=1;
 61     while (true)
 62     {
 63         memset(in,127,sizeof(in));
 64         for (int i=1;i<=m;i++)
 65         {
 66             if (edge[i].c<in[edge[i].v]&&edge[i].u!=edge[i].v)
 67             {
 68                 in[edge[i].v]=edge[i].c;
 69                 pre[edge[i].v]=edge[i].u;
 70             }
 71         }
 72         in[root]=0;
 73         int cnt=0;
 74         memset(id,-1,sizeof(id));
 75         memset(vis,-1,sizeof(vis));
 76         for (int i=1;i<=n;i++)
 77         {
 78             ans+=in[i];
 79             v=i;
 80             while (vis[v]!=i&&v!=root&&id[v]==-1)
 81             {
 82                 vis[v]=i;
 83                 v=pre[v];
 84             }
 85             if (v!=root&&id[v]==-1)
 86             {
 87                 id[v]=++cnt;
 88                 for (int u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
 89             }
 90         }
 91         if (cnt==0) break;
 92         for (int i=1;i<=n;i++) if (id[i]==-1) id[i]=++cnt;
 93         for (int i=1;i<=m;i++)
 94         {
 95             v=edge[i].v;
 96             edge[i].u=id[edge[i].u];
 97             edge[i].v=id[edge[i].v];
 98             if (edge[i].u!=edge[i].v) edge[i].c-=in[v];
 99         }
100         n=cnt;
101         root=id[root];
102     }
103     return ans;
104 }

 

 

[Awson原创]修水渠(canal)

标签:put   mat   using   inpu   stack   memset   nbsp   style   string   

原文地址:http://www.cnblogs.com/NaVi-Awson/p/7252420.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!