CodeForces 400D (最短路+并查集) Dima and Bacteria

来源:互联网 发布:创世写作 mac 编辑:程序博客网 时间:2024/05/29 18:26


Description

Dima took up the biology of bacteria, as a result of his experiments, he invented k types of bacteria. Overall, there are n bacteria at his laboratory right now, and the number of bacteria of type i equals ci. For convenience, we will assume that all the bacteria are numbered from 1to n. The bacteria of type ci are numbered from  to .

With the help of special equipment Dima can move energy from some bacteria into some other one. Of course, the use of such equipment is not free. Dima knows m ways to move energy from some bacteria to another one. The way with number i can be described with integers ui, viand xi mean that this way allows moving energy from bacteria with number ui to bacteria with number vi or vice versa for xi dollars.

Dima's Chef (Inna) calls the type-distribution correct if there is a way (may be non-direct) to move energy from any bacteria of the particular type to any other bacteria of the same type (between any two bacteria of the same type) for zero cost.

As for correct type-distribution the cost of moving the energy depends only on the types of bacteria help Inna to determine is the type-distribution correct? If it is, print the matrix d with size k × k. Cell d[i][j] of this matrix must be equal to the minimal possible cost of energy-moving from bacteria with type i to bacteria with type j.

Input

The first line contains three integers n, m, k(1 ≤ n ≤ 105; 0 ≤ m ≤ 105; 1 ≤ k ≤ 500). The next line contains k integersc1, c2, ..., ck(1 ≤ ci ≤ n). Each of the next m lines contains three integers ui, vi, xi(1 ≤ ui, vi ≤ 105; 0 ≤ xi ≤ 104). It is guaranteed that .

Output

If Dima's type-distribution is correct, print string «Yes», and then k lines: in the i-th line print integers d[i][1], d[i][2], ..., d[i][k](d[i][i] = 0). If there is no way to move energy from bacteria i to bacteria j appropriate d[i][j] must equal to -1. If the type-distribution isn't correct print «No».

Sample Input

Input
4 4 21 32 3 03 4 02 4 12 1 2
Output
Yes0 22 0
Input
3 1 22 11 2 0
Output
Yes0 -1-1 0
Input
3 2 22 11 2 02 3 1
Output
Yes0 11 0
Input
3 0 21 2
Output
No



题意:英文实在不行,大概描述一下,第一行给定n,m,k个集合(其实是k种细菌)。n代表n个点。(其实是n个细菌。)并且1到n编号。第二行给出k个集合的点数量。(其实是k种细菌的数量)。下面m行,给出m条边(其实是m种仪器。。)给出u,v,x代表编号为u的点(细菌),到编号为v的点,需要花费x的能量。

问的是是否满足同种细菌移动的能量为0。如果满足的话,输出一个k*k行的矩阵,代表不同集合(细菌)的点之间互相移动所需要最小的花费。

假如有一个集合无法到达另一个集合,输出-1.

题目实在是太抽象了。。。

简述,就是给你n个点,m条边。K个集合,k个集合的点数,满足每个集合任意两点之间移动所需要的花费为0。求的是任意两个集合移动所需要的花费。

思路:先给每个集合的点编号。然后存入图里面。然后用并查集判断是否满足同个集合任意两点距离为0。(相当于所有的点他们的关系构成一个集合)。

如果满足的话,接下来floyd 求传递闭包,算出任意两个集合的点移动所需要的花费,如果不能到达,令其值为负一。

注意:n,m的范围很大,输入要用long long or __int64。

上代码

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstring>#include <map>#include <stack>#include <vector>#include <set>#include <queue>#define N 100005#define M 505#define maxn 100005#define MAXN 200005#define mod 1000000009#define INF 0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-6typedef long long ll;using namespace std;ll n,m,k;ll fa[N];ll num[N];ll belong[N];ll mpt[M][M];ll find(ll x)  //查找{    if(x!=fa[x])        fa[x]=find(fa[x]);    return fa[x];}void hebing(ll x,ll y)  //并查集{    x=find(x);    y=find(y);    fa[y]=x;}bool judge(){    ll i,j,p;    p=1;    for(i=1; i<=k; i++)    {        int x=find(p);        for(j=1; j<=num[i]; j++)            if(find(p++)!=x)                return 0;    }   //用并查集判断一个集合内的任意两点是否花费为0。    return 1;}void floyd() //floyd 算法求传递闭包。用边联通所有有关系的点,并且算出任意两点的最短距离{    for(ll p=1; p<=k; p++)    {        for(ll i=1; i<=k; i++)        {            for(ll j=1; j<=k; j++)            {                mpt[i][j]=min(mpt[i][j],mpt[i][p]+mpt[p][j]);            }        }    }}int main(){    ll i,j,p;    while(scanf("%lld%lld%lld",&n,&m,&k)!=EOF)    {        memset(mpt,INF,sizeof(mpt));        for(i=1; i<=k; i++)            for(j=1; j<=k; j++)            {                if(i==j)                    mpt[i][j]=mpt[j][i]=0;                else                    mpt[i][j]=mpt[j][i]=INF; //初始化不同集合的边。            }            for(i=1; i<=n; i++)            fa[i]=i;  //并查集的初始化        p=1;        for(i=1; i<=k; i++)        {            scanf("%lld",&num[i]);  //一个集合            for(j=1; j<=num[i]; j++)                belong[p++]=i;   //给每个集合的每个点编号        }        ll u,v,w,uu,vv;        while(m--)        {            scanf("%lld%lld%lld",&u,&v,&w);            if(!w)                hebing(u,v);  //花费为0就合并。。            uu=belong[u];  //把编号存入图里            vv=belong[v];   //同上            mpt[uu][vv]=mpt[vv][uu]=min(mpt[uu][vv],w);        }        if(!judge())        {            printf("No\n");  //判断是否满足            continue;        }        printf("Yes\n");        floyd();        for(i=1; i<=k; i++)        {            for(j=1; j<=k; j++) //枚举所有的不同集合            {                if(i==j)                    mpt[i][j]=0;                if(mpt[i][j]==INF)  //不能到达                    mpt[i][j]=-1;   //令为负一                if(j<k)                    printf("%lld ",mpt[i][j]);                 else                    printf("%lld",mpt[i][j]);            }            printf("\n");        }    }    return 0;}


0 0
原创粉丝点击