本以为用并查集,于是兴致勃勃写了并查集的做法,由于给的测试实例太弱,于是测试没问题就交了,结果WA,于是百度一下,发现大部分人用的是拓扑排序和floyd算法,于是满怀信心的学拓扑,结果整了一个晚上没明白,第二天依然不太明白,于是改学拓扑,代码也不太好理解,便问了同志们,他们说自己也是不太理解,就这样用了,当模板了,于是便想先用着吧,希望再用的过程中会理解点什么;下面提供一下我自己对dijkstra和floyd的理解;
对于dijkstra算法概要就是要定义一个二维数组和一个一维数组;
二维数组就是把从第i到第j的路径的权值记下来,而且从i到j与从j到i是一样的,
一维数组就是记录从i到j的最小(或最大)的权值,逐步增加所可以增加的点,使之入住,之后更新权值;
重复以上过程,直到结束,count[j]即是从i到j的最小(或最大);
主要代码如下:
int MAX 2147483647;
int k,x,y;//x为起点,y为终点
int n;///n是根据需要取得二维数组的大小:n^n;
for(i=0;i<n;i++)
{
flag[i]=0;
count[i]=map[x][i];
}
flag[0]=1;
count[0]=0;
for(i=0;i<n;i++)
{
min=MAX
for(j=0;j<n;j++)
{
if(flag[j]==0&&count[j]<min)
{
min=count[j];
k=j;
}
}
flag[k]=1;///每次都把它处理成1,由于,flag[]是一维数组,上面的遍历i=n次足够;
for(j=0;j<n;j++)
if(flag[j]==0&&count[j]>count[k]+map[k][j])
count[j]=count[k]+map[k][j];
return count[y];//
}
floyd算法就是递推出一个数列,a0,a1,a2,……ak,……an;
其中ak[i][j],就是从i到j的路径序号不大于k的路径的最短长度;
初始时a0为邻接矩阵,
a(k+1)[i][j]=min(ak[i][j],ak[i][k+1]+ak[k+1][j]);
主要代码如下:
for(k=0;k<n;k++)
for(j=0;j<n;j++)
for(i=0;i<n;i++)
if(map[j][i]<map[j][k]+map[k][i])
map[j][i]=map[j][k]+map[k][i];
代码长度虽不长,可是具体运行的过程并不是很理解,有待单步调试;
此题代码如下:
# include<stdio.h> # include<string.h> int main() { int n,m,i,j,k,map[120][120],flag; while(scanf("%d%d",&n,&m),n||m) { memset(map,0,sizeof(map)); for(i=0;i<m;i++) { scanf("%d%d",&j,&k); map[j][k]=1; } for(k=0;k<n;k++) for(j=0;j<n;j++) for(i=0;i<n;i++) if(map[j][k]==1&&map[k][i]==1) map[j][i]=1; flag=0; for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { if(map[i][j]==1&&map[j][i]==1) { flag=1; break; } } if(flag==1) break; } if(flag==0) printf("YES\n"); else printf("NO\n"); } return 0; }