CSUOJ-1633 Landline Telephone Network

CSUOJ--1633 Landline Telephone Network

其实就是一道最小生成树的题目.我们只需要将坏点排除在外,然后对其它点做一次最小生成树,然后在将坏点连接到这颗生成树上(每次都选代价最小的点).当然如果最后不是所有的点都连接到一起,就是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;
}