POJ1860 Currency Exchange(最短路径,有无正环,模板)

来源:互联网 发布:python文本相似性 编辑:程序博客网 时间:2024/06/06 18:07

POJ1860
题意分析:
给定N种货币,某些货币之间可以相互兑换,现在给定一些兑换规则,问能否从某一种货币开始兑换,经过一些中间货币之后,最后兑换回这种货币,并且得到的钱比之前的多。
及判断是否存在正环。

链式前向星存储图(边存储)详解:http://blog.csdn.net/acdreamers/article/details/16902023
http://blog.csdn.net/cfhm_r/article/details/50771597

spfa算法判断是否存在正环,模板:

#include<cstdio>#include<cstring>#include<queue>using namespace std;#define MAX 101struct node{    int to;    double r,c;    int next;}edge[MAX*2];int head[MAX],tol;int N,M,S;double V;void add(int st,int end,double r,double c){    edge[tol].to = end;    edge[tol].r = r;    edge[tol].c  =c;    edge[tol].next = head[st];    head[st] = tol++;}void init(){    int i;    for(i = 1 ; i <= N ; i ++) head[i] = -1;    tol = 0;    int a,b;    double c,d;    for(i = 0 ; i < M ; i ++)    {        scanf("%d%d%lf%lf",&a,&b,&c,&d);        add(a,b,c,d);        scanf("%lf%lf",&c,&d);        add(b,a,c,d);    }}double d[MAX];int cnt[MAX];//记录入队次数bool flag[MAX];bool spfa(){    int i;    for(i = 1 ; i <= N ; i ++) flag[i] = false,d[i] = 0,cnt[i] = 0;    d[S] = V;//我们这里把初始的d 置为 V,也就是现有的钱数,    queue<int>q;    q.push(S);    cnt[S]++;    while(!q.empty())    {        int u=q.front();q.pop();flag[u]=false;        for(int j = head[u] ; j != -1 ; j = edge[j].next)        {            int v = edge[j].to;            double r = edge[j].r, c = edge[j].c;            if(d[v] < (d[u]-c)*r)//这里就是需要转变一点点的松弛操作            {                d[v] = (d[u]-c)*r;                if(!flag[v])                     flag[v] = true,cnt[v] ++,q.push(v);                if(cnt[v] > N) //如果入队次数大于点数,那么就是有回路                    return true;            }        }    }    return false;}int main(){    scanf("%d%d%d%lf",&N,&M,&S,&V);    init();    if(spfa())        printf("YES\n");    else        printf("NO\n");    return 0;}

————————————————————————————————————————————————————————————
第一次邻接矩阵写的,WA了,求教:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string.h>#include<queue>#define maxn 110#define inf 0x3f3f3fusing namespace std;int n,m,w;int sta;double sw;int dis[maxn],cnt[maxn];bool vis[maxn];struct node{    int end;    double r,c;};vector<node> v[maxn]; //邻接表bool spfa(){    memset(vis,false,sizeof(vis));    memset(dis,inf,sizeof(dis));    memset(cnt,0,sizeof(cnt));    dis[sta]=sw,vis[sta]=true,cnt[sta]=1;    queue<int> q;    q.push(sta); //源点入队    while(!q.empty())    {        int x=q.front();        q.pop();        vis[x]=false;        int len=v[x].size ();          //遍历以头结点x为起始点的所有边的终点        for(int i=0;i<len;i++)        {            int ed=v[x][i].end ;            double r=v[x][i].r ;            double c=v[x][i].c ;        //如果实现了松弛并且该点不在队列中,则入队            if(dis[ed]<(dis[x]-c)*r)            {                dis[ed]=(dis[x]-c)*r;                if(!vis[ed])                {                    vis[ed]=true;                    cnt[ed]++;        //如果一个结点入队的次数多于n,则存在负环                    if(cnt[ed]>=n) return true;                        q.push (ed);                }            }        }    }    return false;}int main(){    int i,s,e;    double r1,r2,c1,c2;        node a;        cin>>n>>m; //n个点,m个双向边        cin>>sta>>sw;        for(i=0;i<n;i++)            v[i].clear ();        for(i=0;i<m;i++){  //双向边            cin>>s>>e>>r1>>c1>>r2>>c2;            a.end=e,a.r=r1,a.c=c1;            v[s].push_back (a);            a.end =s, a.r =r2,a.c=c2;            v[e].push_back (a);        }        if(spfa())            cout<<"YES"<<endl;        else cout<<"NO"<<endl;    return 0;}