题目链接:( ̄▽ ̄)
思路:它的题意是判断有没有正权回路,起点没有规定是哪个点(没读清楚wa了n次, 不是从第一个点判断正权回路)
Ps:第一道spfa题~( ̄▽ ̄~)(~ ̄▽ ̄)~
code:
#include <stdio.h>
#include <string.h>
typedef struct
{
int v, next;
double p;
}node;
node edge[10000];
int n = 0, used[40], visit[40], head[40], flag = 0;
double dis[40];
char str[40][30], str1[40], str2[40];
int find(char *str1)
{
int i = 0;
for(i = 0; i<n; i++)
{
if(strcmp(str[i], str1) == 0)
return i;
}
return i;
}
void spfa(int k)
{
int i = 0, quene[1000], front = 0, rear = 0, cur = 0, item = 0;
for(i = 0; i<n; i++)//每回都要初始化
{
used[i] = visit[i] = 0;
dis[i] = 0;
}
quene[rear++] = k;
used[k] = 1; dis[k] = 1;
while(front<rear)
{
cur = quene[front++];//cur为当前点
item = head[cur];//item为当前点在edge[]中邻边所存的信息
used[cur] = 0;
while(item != -1)
{
if(dis[edge[item].v]<dis[cur]*edge[item].p)//可以进行松弛
{
dis[edge[item].v] = dis[cur]*edge[item].p;
if(visit[edge[item].v]>n+1)//一个点入队n次表明必存在回路
{
flag = 1;
return ;
}
if(!used[edge[item].v])//用used标记该点在不在队列中
{
used[edge[item].v] = 1;
visit[edge[item].v]++;//该点入队次数
quene[rear++] = edge[item].v;
}
}
item = edge[item].next;//读取下一个邻边在edge[]中的位置
}
}
}
int main()
{
int i = 0, m = 0, a = 0, b = 0, count = 0;
double p = 0;
while(scanf("%d",&n), n)
{
getchar();
flag = 0;
for(i = 0; i<n; i++)
{
head[i] = -1;
gets(str[i]);
}
scanf("%d",&m);
getchar();
for(i = 0; i<m; i++)
{
scanf("%s",str1);
scanf("%lf",&p);
scanf("%s",str2);
a = find(str1);
b = find(str2);
edge[i].v = b;
edge[i].p = p;
edge[i].next = head[a];
head[a] = i;
}
for(i = 0; i<n; i++)//以第i个顶点为起点, 看有没有正权回路
{
if(!flag)
spfa(i);
}
printf("Case %d: ",++count);
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}