2017暑假集训 div1 最短路(2)

来源:互联网 发布:河南省863软件孵化器 编辑:程序博客网 时间:2024/06/05 16:28

POJ 3660

题意:给出m对牛的相互关系,求有多少个牛排名是确定的。

做法:用floyd求传递闭包。如果 A>B, B>C 那么一定有 A>C  与Floyd 的 枚举三个点一模一样!!!


核心代码:

void floyd(){    for(int i=1;i<=n;++i)    {        for(int j=1;j<=n;++j)        {            for(int k=1;k<=n;++k)            {                if(map[j][i]&&map[i][k]) map[j][k]=1;            }        }    }}


HDU 1217&&POJ2240
题意:给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。举例说就是1美元经过一些兑换之后,超过1美元。可以输出Yes,否则输出No。

做法:由于给出的是货币名称,所以首先我们要把货币之间的关系转化成一张图。转化时,直接用map标记号,然后就spfa 求负环问题了


POJ 1511

题意:给定节点数n,和边数m,边是单向边.问从1节点出发到2,3,...n 这些节点路程和从从这些节点回来到节点1的路程和最小值。

做法:直接正反两边spfa 扫一遍求和即可(存邻接表的同时,把反向邻接表也存上)


POJ 3159
题意:n表示有n个同学,m表示m组数据u,v,w,表示同学u要求同学v的糖果数不能多于他超过w个,问同学n和同学1的他糖果数最多相差几个??

做法:差分约束,条件很明显,运用类似最短路分析d[v] - d[u] <= w(u, v) ,也就是 d[v] <= w(u,v) + d[u];每个约束B-A<=c 就是B<=A+c  加边A->B  为c的边。用优先队列优化的dij ,求最短路

代码:


#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#include <algorithm>using namespace std;const int inf=0x3f3f3f3f;const int maxn=30010;struct node{    int next,to;    int  w;}edge[200000];int head[maxn],cnt=0;void add(int u,int v,int w){    edge[cnt].to=v; edge[cnt].w= w;    edge[cnt].next= head[u] ; head[u]=cnt++;}int n,m;bool vis[maxn];int dis[maxn];struct enode{    int pos,val;    bool friend operator < (const enode a,const enode b)    {        return a.val>b.val;    }};void dij(){    for(int i=1;i<=n;++i)    {        vis[i]=0; dis[i]=inf;    }    dis[1]=0;    struct enode u,v;    priority_queue<enode>  que;    while(!que.empty()) que.pop();    u.pos=1; u.val=0;    que.push(u);    while(!que.empty())    {        u=que.top() ; que.pop();        if(vis[u.pos]) continue;        vis[u.pos]=1;        for(int i=head[u.pos];i!=-1;i=edge[i].next)        {            int to=edge[i].to;            int w=edge[i].w;            if(!vis[to]&&dis[u.pos]+w<dis[to])            {                dis[to]=dis[u.pos]+w;                v.pos= to; v.val=dis[to];                que.push(v);            }        }    }}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(head,-1,sizeof(head)); cnt=0;        for(int i=1;i<=m;++i)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add(a,b,c);        }        dij();        printf("%d\n",dis[n]);    }    return 0;}










原创粉丝点击