[POJ 3164]コマンドネットワーク最小の木

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/ALPS233/article/details/51556216

トピックhttp://poj.org/problem?id=3164

コマンドネットワーク

制限時間:1000msのメモリ制限:131072K
合計提出:16037受理:4623

説明

言葉の長期的な戦争の後、腕に戦争は最終的にlittlekenのとKnuthOceanの王国の間で勃発します。KnuthOceanの力によって突然の暴力的な攻撃はlittlekenのコマンドネットワークの完全な失敗をレンダリングしています。暫定ネットワークはすぐに構築する必要があります。littleken受注はプロジェクトの責任を取るためにスヌーピー。

細部にまで研究の状況では、スヌーピーが最も緊急のポイントが破壊されたネットワーク内のすべての切断ノードに到達するためにlittenkenのコマンドを有効にすることであり、一方向の通信ネットワークを構築する計画を決定すると考えています。ノードは、平面上に分布しています。littlekenのコマンドは、別のノードAからノードBに直接送達することができるようになっている場合、ワイヤは、2つのノードを結ぶ線分に沿って構築されなければなりません。それは戦時中ではなく、すべてのノード対の間だからワイヤを構築することができます。スヌーピーは、建設は非常にすぐに行うことができるように、配線の最短全長を必要とする計画を望んでいます。

入力

入力は、いくつかのテストケースが含まれています。各テストケースは、2つの整数N(N 100以下)、破壊されたネットワーク内のノードの数、及びM(M≤104)、ワイヤが構築できるとの間のノードのペアの数を含む行から始まります。次のN行はそれぞれのノードのデカルト座標を与え、順序対Xi及びYIを含みます。次いで、M線をiとj 1及びワイヤーを意味N(両端を含む)の間には、後者に前者から一方向コマンド送達のためにノードiとノードjとの間で構築することができるそれぞれ含む2つの整数を辿ります。littlekenの本社は、常にファイルの末尾にノード1のプロセスに位置しています。

出力

各テストケースのために、出力を正確小数点過去二桁のワイヤの最短全長を含む一行。そのようなネットワークが存在しないことのケースでは、単に出力「貧しいスヌーピー」。

サンプル入力
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

サンプル出力
31.19
貧しいスヌーピー

アイデア:
参照してくださいhttp://blog.csdn.net/shuangde800/article/details/8039359
ここで説明する絵を書きます

すなわち:*役に立たない側から、削除、
接続1図の決意を、解が直接通信しない場合、そうでなければ少なくとも一つの溶液を。
       2.すべてのノードは、回答などの無環なかった、容易に入手可能なプレ[]、[]ミネソタ州を、記録、最短辺を見つけるために、
       リング3、もしリング[]の縁にANS収縮点+ =エッジ、エッジ[]エッジを縮小する点- =ミネソタ州[x]は、図に示すように、(*不要な側から、削除);
       非環式の4リピート、休憩

コード

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;


int n,m;
struct node{
    double x,y;
}p[1005];
struct edge{
    int x,y;
    double v;
}q[1005*105];
double in[1005];
int pre[1005];
int vis[1005],id[1005];
double inf=99999999.9;
double solve()
{
    double ret=0.0;
    int nn=n;
    int rt=1;
    while(1)
    {
        for(int i=1;i<=nn;i++) in[i]=inf;

        for(int i=1;i<=m;i++)
        {
            if(q[i].x!=q[i].y&&in[q[i].y]>q[i].v)
            {
                pre[q[i].y]=q[i].x;
                in[q[i].y]=q[i].v;
            }
        }

        for(int i=1;i<=nn;i++)
        {
            if(i==rt) continue;
            if(in[i]==inf) return -1;
        }

        int cnt=0;
        memset(id,-1,sizeof(id));
        memset(vis,-1,sizeof(vis));
        in[rt]=0;

        for(int i=1;i<=nn;i++)
        {
            ret+=in[i];

            int now=i;
            while(now!=rt&&vis[now]!=i&&id[now]==-1)
            {
                vis[now]=i;
                now=pre[now];
            }

            if(now!=rt&&id[now]==-1)
            {
                cnt++;
                for(int nex=pre[now];nex!=now;nex=pre[nex])  id[nex]=cnt;
                id[now]=cnt;
            }
        }
        if(cnt==0)  break;
        for(int i=1;i<=nn;i++)
        if(id[i]==-1) id[i]=++cnt;

        for(int i=1;i<=m;i++)
        {
            int xx=q[i].x;
            int yy=q[i].y;
            q[i].x=id[xx];
            q[i].y=id[yy];
            if(id[xx]!=id[yy]) q[i].v-=in[yy];
        }
        nn=cnt;
        rt=id[rt];
    }
    return ret; 
}

double dis(node a, node b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        scanf("%lf%lf",&p[i].x,&p[i].y);

        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].x,&q[i].y);
            if(q[i].x!=q[i].y) q[i].v=dis(p[q[i].x],p[q[i].y]);

            else q[i].v=inf;    
        } 
        double ans=solve();

        if(ans==-1) printf("poor snoopy\n");
        else printf("%.2f\n", ans);
    }
}

おすすめ

転載: blog.csdn.net/ALPS233/article/details/51556216