6:地震之后
-
总时间限制:
- 1000ms 内存限制:
- 130000kB
-
描述
-
2008年地震之后,坚强县受灾严重,该县通信线路也收到了致命的打击,县总部为了能够及时的向各村的发送消息,命令小强去解决一下这个问题。
小强经过调查发现,为了能够快速的实现通信,当务之急是能够建立起一条从总部可以向各个村单向发送信息的通信系统。由于灾后情况紧急,不是每一个村之间都能够快速的建立起通信线路,只有有限的村比如村A和村B间可以建立单向的从A向B发送信息的通信线路,小强现在的问题就是要找出一个合适的方案,使从总部发送出的信息能够通到各村,而用的总的通信线路是最短的(毕竟情况危急,物质短缺)。
输入
-
输入包括多组的测试数据。
对于每一组测试数据:
1、第一行包括两个整数N(1<=N<=100),M(M<<=10000),N表示通信网络中村子的数量,M表示在这些村子中,可以有M条通信线路建起来。
2、接下来N行,每行两个整数xi,yi,代表着这个村子的X轴,Y轴的坐标(xi,yi)
3、接下来M行,每行两个整数c1(1<=c1<=N),c2(1<=c2<=N),代表着从村c1到村c2可以建一个单向线路。
注:两村之间的直线段距离(通信线路长度),即为两点间的欧式距离。
县总部所在的村假设都在编号为1的村。
输入以文件终止为结束。
输出
-
对于每一组的测试数据,输出完全的一行,值为最短的总长度,结果保留两位小数。
如果不能建立一个单向的临时网络,输出"NO".
样例输入
-
4 6 3 6 4 6 3 4 7 20 1 2 1 3 2 3 3 4 3 1 3 2 4 3 0 0 1 0 1 1 1 2 1 3 4 1 2 3
样例输出
-
19.49 NO
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<iomanip> #include<queue> #include<stack> #include<vector> #include<set> #include<map> using namespace std; struct Node { int x,y; }p[105]; struct Edge { int s,t; double w; }e[10005]; double Inw[105]; int vis[105]; int newid[105]; int pre[105]; double Dis(int s,int t) { double a=p[s].x-p[t].x; double b=p[s].y-p[t].y; return sqrt(a*a+b*b); } double DirMST(int root,int n,int m) { double ans=0; while(true) { for(int i=0;i<n;++i) Inw[i]=0x7fffffff>>1; for(int i=0;i<m;++i) { int s=e[i].s,t=e[i].t; if(s==t)continue; if(e[i].w<Inw[t]) { Inw[t]=e[i].w; pre[t]=s; } } for(int i=0;i<n;++i) { if(i==root)continue; if(Inw[i]==0x7fffffff>>1)return -1; } for (int i=0; i<n; ++i) { vis[i]=-1; newid[i]=-1; } int num=0; Inw[root]=0; for(int i=0;i<n;++i) { ans+=Inw[i]; int v=i; while(vis[v]!=i&&newid[v]==-1&&v!=root) { vis[v]=i;v=pre[v]; } if(v!=root&&newid[v]==-1) { for(int u=pre[v];u!=v;u=pre[u]) { newid[u]=num; } newid[v]=num; num++; } } if(num==0)return ans; for(int i=0;i<n;++i) { if(newid[i]==-1) newid[i]=num++; } for(int i=0;i<m;++i) { int s=e[i].s,t=e[i].t; e[i].s=newid[s]; e[i].t=newid[t]; if(e[i].s!=e[i].t) { e[i].w-=Inw[t]; } } n=num; root=newid[root]; } } int main() { int n,m,x,y; while(scanf("%d",&n)!=EOF) { scanf("%d",&m); for(int i=0;i<n;++i) { scanf("%d%d",&p[i].x,&p[i].y); } for(int i=0;i<m;++i) { scanf("%d%d",&e[i].s,&e[i].t); e[i].s--;e[i].t--; e[i].w=Dis(e[i].s,e[i].t); } double ans; ans=DirMST(0,n,m); if(ans==-1)printf("NO\n"); else printf("%.2f\n",ans); } return 0; }