CSU 1633: Landline Telephone Network (最小生成树)

来源:互联网 发布:广州多益网络怎么样 编辑:程序博客网 时间:2024/06/07 08:39

1633: Landline Telephone Network

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 63  Solved: 8
[Submit][Status][Web Board]

Description

The mayor of RMRCity wants to create a secure landline telephone network for emergency use in case of serious disasters when the city is cut off from the outside world. Some pairs of buildings in the city can be directly connected with a wire telephone line and the municipality engineers have prepared an estimate of the cost of connecting any such pair.
The mayor needs your help to find the cheapest network that connects all buildings in the city and satisfies a particular security measure that will be explained shortly. A call from a building A to another building B may be routed through any simple path in the network (i.e., a path that does not have any repeated building). There are also some insecure buildings that one or more persons with serious criminal records live in. The mayor wants only communications intended for these insecure buildings to reach them. In other words, no communication from any building A to any building B should pass through any insecure building C in the network (where C is different from A and B).

Input

The input consists of a single test case. The first line contains three integers n, m, p where 1 ≤ n ≤ 1000 is the number of buildings, 0 ≤ m ≤ 100000 is the number of possible direct connections between a pair of buildings, and 0 ≤ p ≤ n is the number of insecure buildings. The buildings are numbered from 1 to n.
The second line contains p distinct integers between 1 and n (inclusive), which are the numbers of insecure buildings. Each of the next m lines contains three integers xi, yi, and li describing one potential direct line, where xi and yi (1 ≤ xi, yi ≤ n) are the distinct buildings the line connects, and li (1 ≤ li ≤ 10000) is the estimate of the cost of connecting these buildings. There is at most one direct link between any two buildings in these m lines.

Output

Display the cost of the cheapest network satisfying the security measure if it is possible. Otherwise, display
impossible.

Sample Input

4 6 111 2 11 3 11 4 12 3 22 4 43 4 3

Sample Output

6

HINT

题意:有n个点,m条边,p个不安全点(p<=n),接下来一行输入p个不同的数代表不安全的点。再输入m行 a b c,表示a 点与b 点相连需花费c,  现在需把所有的点连起来花费最少,但必须满足一个条件:任意一个点A 到任意一个点B 所经过的路径中不能经过 不安全的点C  (A,B,C各不相同),问最少需要花费多少使这n个点相连,如果不能满足要求则输出 impossible
解题:先把n个点分成两部分:安全点,不安全点。再先把安全点用prime算法建一棵最小生成树,如果不能建成就可以输出impossible,如果可以,再向这棵树加不安全点做为叶子节点,每加一个不安全点找出一个与之相连的安全点边权最小的。如果找不到与之相连的安全点则不能满点要求。有特判:安全点为0,不安全点数等于1或2或 >=3时。
#include<stdio.h>#include<string.h>const int N = 1005;const int INF = 1<<28;int mapt[N][N],n,flag[N],p;int prime(){    int s[N],dis[N],mint,m,tm,k=0,sum=0;    for(int i=1; i<=n; i++){        s[i]=0; dis[i]=INF;        if(flag[i]==0)            m=i,k=1;    }    if(k==0)        return 0;    dis[m]=0; s[m]=1; tm=m;    while(k<n-p){        mint=INF;        for(int i=1; i<=n; i++)        if(!s[i]&&flag[i]==0){            if(dis[i]>mapt[m][i])                dis[i]=mapt[m][i];            if(mint>dis[i])                mint=dis[i],tm=i;        }        if(mint==INF)return -1;        m=tm; s[m]=1; sum+=mint; k++;    }    return sum;}int main(){    int m,a,b,c,aa[N];    while(scanf("%d%d%d",&n,&m,&p)>0){        for(int i=1; i<=n; i++){            flag[i]=0;            for(int j=1; j<=n;j++)                mapt[i][j]=INF;        }        for(int i=1; i<=p; i++){            scanf("%d",&a);            flag[a]=1; aa[i]=a;        }        while(m--){            scanf("%d%d%d",&a,&b,&c);            if(c<mapt[a][b])                mapt[a][b]=mapt[b][a]=c;        }        int sum=prime();        if(sum==-1)            printf("impossible\n");        else{             if(n-p==0)             {                 if(p==1)printf("0\n");                 else if(p==2){                    a=aa[1]; b=aa[2];                    if(mapt[a][b]==INF)                    printf("impossible\n");                    else printf("%d\n",mapt[a][b]);                 }                 else printf("impossible\n");                 continue;             }            int i,j,mint;            for(i=1; i<=p; i++){                a=aa[i]; mint=INF;                for(j=1;j<=n;j++)                if(mapt[a][j]<mint&&flag[j]==0)                   mint=mapt[a][j];                if(mint==INF)                    break;                sum+=mint;            }            if(i<=p)                printf("impossible\n");            else printf("%d\n",sum);        }    }    return 0;}


0 0
原创粉丝点击