码迷,mamicode.com
首页 > Web开发 > 详细

CSUOJ--1633 Landline Telephone Network

时间:2015-05-25 10:12:19      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:最小生成树

其实就是一道最小生成树的题目.我们只需要将坏点排除在外,然后对其它点做一次最小生成树,然后在将坏点连接到这颗生成树上(每次都选代价最小的点).当然如果最后不是所有的点都连接到一起,就是impossible了.
还有一种情况需要特判,就是如果一共只有两个点,并且都是坏点,这种情况也是合法的.

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

#define maxn 210000
#define ll long long
#define INF 0x3f3f3f3f

vector<int>g[maxn],w[maxn];

typedef struct
{
    int x,y,w;
}P;
P p[maxn];

int cmp(P p1,P p2)
{
    return p1.w<p2.w;
}

int e,fa[maxn];
int a[maxn],flag[maxn];

int Find(int x)
{
     return fa[x]==x?x:Find(fa[x]);
}

///如果只有两个点,且全部是坏点则要特判
int main()
{
      int n,m,k;
     // freopen("in.txt","r",stdin);
      while(scanf("%d%d%d",&n,&m,&k)!=EOF)
      {
              int h;
              memset(flag,0,sizeof(flag));
              for(int i=1;i<=n;i++)
                  fa[i]=i;
              for(int i=1;i<=n;i++)
                 g[i].clear(),w[i].clear();
              for(int i=0;i<k;i++)
              {
                    scanf("%d",&a[i]);
                    flag[a[i]]=1;
              }
              e=0;
              for(int i=1;i<=m;i++)
              {
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    if(k==2&&x==a[0]&&y==a[1]) h=z;
                    if(k==2&&y==a[0]&&x==a[1]) h=z;
                    p[e].x=x; p[e].y=y; p[e].w=z; e++;
                    p[e].x=y; p[e].y=x; p[e].w=z; e++;
                    g[x].push_back(y); w[x].push_back(z);
                    g[y].push_back(x); w[y].push_back(z);
              }
              if(n==2&&k==2)
              {
                    printf("%d\n",h);
                    continue;
              }
              sort(p,p+e,cmp);
              int cnt=1;
              bool bl=true;
              ll ans=0;
              for(int i=0;i<e;i++)
              {
                   int x=p[i].x,y=p[i].y;
                   if(!flag[x]&&!flag[y])
                   {
                         int xx=Find(x);
                         int yy=Find(y);
                         if(xx!=yy)
                         {
                              ans+=p[i].w; cnt++;
                              fa[xx]=yy;
                         }
                   }
              }
              if(cnt<n-k)  bl=false;
              int sum1=0,sum2=0;
              for(int i=0;i<k;i++)
              {
                     int x=a[i],y,tmp=INF;
                     for(int j=0;j<g[x].size();j++)
                     {
                           y=g[x][j];
                           if(flag[y])
                              continue;
                           if(tmp>w[x][j])
                               tmp=w[x][j];
                     }
                     if(tmp<INF)
                        ans+=tmp,cnt++;
              }
              if(cnt<n) bl=false;
              if(!bl)
                  printf("impossible\n");
              else
                  printf("%lld\n",ans);
      }
   return 0;
}

CSUOJ--1633 Landline Telephone Network

标签:最小生成树

原文地址:http://blog.csdn.net/acm_lkl/article/details/45955071

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