題目連接node
ommand Networkgit
Time Limit: 1000MS | Memory Limit: 131072K | |
Total Submissions: 20041 | Accepted: 5749 |
Description算法
After a long lasting war on words, a war on arms finally breaks out between littleken’s and KnuthOcean’s kingdoms. A sudden and violent assault by KnuthOcean’s force has rendered a total failure of littleken’s command network. A provisional network must be built immediately. littleken orders snoopy to take charge of the project.數組
With the situation studied to every detail, snoopy believes that the most urgent point is to enable littenken’s commands to reach every disconnected node in the destroyed network and decides on a plan to build a unidirectional communication network. The nodes are distributed on a plane. If littleken’s commands are to be able to be delivered directly from a node A to another node B, a wire will have to be built along the straight line segment connecting the two nodes. Since it’s in wartime, not between all pairs of nodes can wires be built. snoopy wants the plan to require the shortest total length of wires so that the construction can be done very soon.dom
Inputide
The input contains several test cases. Each test case starts with a line containing two integer N (N ≤ 100), the number of nodes in the destroyed network, and M (M ≤ 104), the number of pairs of nodes between which a wire can be built. The next N lines each contain an ordered pair xi and yi, giving the Cartesian coordinates of the nodes. Then follow M lines each containing two integers i and j between 1 and N (inclusive) meaning a wire can be built between node i and node j for unidirectional command delivery from the former to the latter. littleken’s headquarter is always located at node 1. Process to end of file.oop
Outputui
For each test case, output exactly one line containing the shortest total length of wires to two digits past the decimal point. In the cases that such a network does not exist, just output ‘poor snoopy
’.spa
Sample Input.net
4 6 0 6 4 6 0 0 7 20 1 2 1 3 2 3 3 4 3 1 3 2 4 3 0 0 1 0 0 1 1 2 1 3 4 1 2 3
Sample Output
31.19 poor snoopy
如下轉自該博客:https://blog.csdn.net/shuangde800/article/details/8039359
題目大意:給定一個有向圖,根節點已知,求該有向圖的最小樹形圖。最小樹形圖即有向圖的最小生成樹,定義爲:選擇一些邊,使得根節點可以到達圖中全部的節點,並使得選出的邊的邊權和最小。
題目算法:朱-劉算法(即由中國人朱永津和劉振宏共同發明的算法)。
算法步驟以下:(本文再也不證實,參考下面給出的我本身畫的一個圖便可理解)
1.判斷圖的連通性,若不連通直接無解,不然必定有解。
2.爲除了根節點之外的全部點選擇一個權值最小的入邊,假設用pre數組記錄前驅,f數組記錄選擇的邊長,記所選邊權和爲temp。
3.(可利用並查集)判斷選擇的的邊是否構成環,若沒有則直接ans+=temp並輸出ans,如有,則進行下一步操做。
4.對該環實施縮點操做,設該環上有點V1,V2……Vi……Vn,縮成的點爲node ,對於全部不在環中的點P進行以下更改:
(1) 點P到node的距離爲min{a[p,Vi]-f[Vi]} (a爲邊集數組)
(2)點node到p的距離爲min{a[Vi,p]}
操做(1)的理解:先假設環上全部邊均選上,若下次選擇某一條邊進入該環,則能夠斷開進入點與進入點的前驅之間的邊,即斷開F[進入點],因此等效爲直接把a[p,node]賦值爲min{a[p,Vi]-f[Vi]}。
特別提醒:本題有自環,能夠提早刪掉,由於它沒有用。
ac代碼
/* http://blog.csdn.net/liuke19950717 */ #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1005; struct point { double x,y; }p[maxn]; struct node { int u,v; double len; }edge[maxn*maxn]; int pre[maxn],id[maxn],vis[maxn]; double in[maxn]; double dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double dir_mst(int root,int n,int m) { double ans=0; while(1) { //先找出全部點的最小入邊 /*memset(in,inf,sizeof(in)); //這樣寫會報錯!*/ for(int i=0;i<n;++i) { in[i]=inf; } for(int i=0;i<m;++i) { int u=edge[i].u,v=edge[i].v; if(edge[i].len<in[v]&&u!=v) { pre[v]=u;in[v]=edge[i].len; } } for(int i=0;i<n;++i) { if(i==root) { continue; } if(in[i]==inf) { return -1; //若是某點入度爲零,一定找不到 } } //檢查這些邊是否構成了環 memset(id,-1,sizeof(id)); memset(vis,-1,sizeof(vis)); in[root]=0; int cnt=0; for(int i=0;i<n;++i)//標記環 { ans+=in[i]; int v=i; while(vis[v]!=i&&id[v]==-1&&v!=root) { vis[v]=i; v=pre[v]; } if(v!=root&&id[v]==-1)//縮點 { for(int u=pre[v];u!=v;u=pre[u]) { id[u]=cnt; } id[v]=cnt++; } } if(cnt==0) { break;//無環 } for(int i=0;i<n;++i) { if(id[i]==-1) { id[i]=cnt++; } } //創建新圖 for(int i=0;i<m;++i) { int u=edge[i].u,v=edge[i].v; edge[i].u=id[u]; edge[i].v=id[v]; if(id[u]!=id[v]) { edge[i].len-=in[v]; } } n=cnt; root=id[root]; } return ans; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=0;i<n;++i) { scanf("%lf%lf",&p[i].x,&p[i].y); } for(int i=0;i<m;++i) { scanf("%d%d",&edge[i].u,&edge[i].v); --edge[i].u;--edge[i].v; if(edge[i].u!=edge[i].v) { edge[i].len=dis(p[edge[i].u],p[edge[i].v]); } else { edge[i].len=inf; } } double ans=dir_mst(0,n,m); if(ans==-1) { printf("poor snoopy\n"); } else { printf("%.2f\n",ans); } } return 0; }