The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest题解

来源:互联网 发布:mac delete 不能删除 编辑:程序博客网 时间:2024/05/16 10:38

Hdu4034 Graph

题目大意:一个n×n的图,(i,j)表示从第i个点到第j个点的最短路径,求原来的图最小的边数是多少?

题目解析:任意两点(i,j)的最短路不能超过从(i,k)->(k,j)所有路径之和,如果相等这样的边(i,j)可要可不要(即失效)

乍一看没思路,分析样例很容易发现问题关键,枚举一条最短路,判断是否有其他两条最短路之和与之相等。

坑点:1.(i,j)(i,k)(k,j)没有任何物理上的长短关系,换句话说,k不一定就位于i,j一条最短路径上,所以i,j,k地位相等,要枚举所有边的情况

           2.注意这样两个逻辑:存在一条边(i,j)满足(i,k)(k,j)与他相等,那么这条边就失效了,一条边不能重复失效多次,所以可以开个标记数组解决;存在一条边(i,j)大于(i,k)(k,j)之和,那么这个图就不存在,所以在枚举过程中要遍历所有可能的情况;

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <climits>#include <map>#include <vector>#include <list>#include <stack>#include <queue>#define eps 1e-5#define pi acos(-1)#define clr(k,v) memset(k,v,sizeof(k));using namespace std;typedef long long ll;const int maxn=1e6+10;const int mod=1000000009;const int SZ = 1<<20;struct fastio{char inbuf[SZ];char outbuf[SZ];fastio(){//高速缓存    setvbuf(stdin,inbuf,_IOFBF,SZ);    setvbuf(stdout,outbuf,_IOFBF,SZ);}}io;int n;int edge[110][110];bool vis[110][110];int main(){    //freopen("input.txt","r",stdin);    int T;cin>>T;int kase=1;    while(T--){       int cnt=0;       clr(vis,0);       cin>>n;       for(int i=0;i<n;i++)            for(int j=0;j<n;j++){                cin>>edge[i][j];                if(edge[i][j]) cnt++;            }       bool ok=true;       for(int i=0;i<n&&ok;i++)         for(int j=0;j<n&&ok;j++)            if(j!=i){             for(int k=0;k<n&&ok;k++){               if(k==i||k==j) continue;               if(edge[i][j]>edge[i][k]+edge[k][j]) ok=false;//存在一边满足就false,所有情况都要遍历               else if(!vis[i][j]&&edge[i][j]==edge[i][k]+edge[k][j]) {cnt--;vis[i][j]=1;}//存在一边相等,这一边就失效了,仅且仅失效一次             }            }       if(!ok) {printf("Case %d: impossible\n",kase++);continue;}       else printf("Case %d: %d\n",kase++,cnt);    }    return 0;}


1 0
原创粉丝点击