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的他糖果数最多相差几个??
题意: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;
}