题单链接
https://vjudge.net/article/752
推荐:4, 5
1. POJ-2387 Til the Cows Come Home
模板题,注意输入是先输入 m 在输入 n
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
#define MAXN 1005
long long n,m;
vector<pair<long long,long long> > graph[MAXN];
long long dis[MAXN];
bool vis[MAXN];
void solve()
{
scanf("%lld%lld",&m,&n);
for (long long i=0,u,v,w; i<m; i++) {
scanf("%lld%lld%lld",&u,&v,&w);
graph[u].push_back(make_pair(v,w));
graph[v].push_back(make_pair(u,w));
}
priority_queue<pair<long long,long long> > Q;
memset(vis,0,sizeof(vis));
memset(dis,0x7f,sizeof(dis));
Q.push(make_pair(0,1));
dis[1]=0;
while (!Q.empty()) {
long long u=Q.top().second;
Q.pop();
if (vis[u])
continue;
vis[u]=1;
if (u==n) {
break;
}
for (long long i=graph[u].size()-1; i>=0; i--) {
pair<long long,long long> I=graph[u][i];
long long v=I.first,w=I.second;
if (!vis[v] && dis[v]>dis[u]+w) {
dis[v]=dis[u]+w;
Q.push(make_pair(-(dis[u]+w),v));
}
}
}
printf("%lld\n",dis[n]);
}
int main()
{
solve();
return 0;
}
2. POJ-2253 Frogger
总点个数少,把所有边弄出来,从小到大排个序,一次插入直到起点终点连通,最后插入的就是。(不是并查集嘛……)
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
#define MAXN 205
struct edge {
int u,v;
double w;
edge(){}
edge(int uu, int vv, double ww) : u(uu),v(vv),w(ww){}
bool operator<(const edge& B) {return w<B.w;}
};
#define DIS(x,y) (sqrt((X[x]-X[y])*(X[x]-X[y])+(Y[x]-Y[y])*(Y[x]-Y[y])))
int n;
vector<vector<edge> > graph;
vector<edge> E;
double X[MAXN],Y[MAXN];
int f[MAXN];
int Fa(int x) {return f[x]==x ? x : f[x]=Fa(f[x]);}
void solve()
{
for (int i=0; i<n; i++)
scanf("%lf%lf",&X[i],&Y[i]);
graph.clear();
graph.resize(n+2);
E.clear();
for (int u=0; u<n; u++)
for (int v=u+1; v<n; v++)
E.push_back(edge(u,v,DIS(u,v)));
sort(E.begin(),E.end());
/*
for (edge e: E) {
printf("%d %d %f\n",e.u,e.v,e.w);
}
*/
for (int i=0; i<n; i++)
f[i]=i;
for (int i=0,mi=E.size(); i<mi; i++) {
int fu=Fa(E[i].u);
int fv=Fa(E[i].v);
f[fu]=fv;
if (Fa(0)==Fa(1)) {
printf("Frog Distance = %.3f\n",E[i].w);
return;
}
}
}
int main()
{
int ttt=0;
while (scanf("%d",&n)==1 && n>0) {
printf("Scenario #%d\n",++ttt);
solve();
puts("");
}
return 0;
}
3. POJ-1797 Heavy Transportation
和上面那题一样……
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 1005
#define MAXM 2000005
struct edge {
int u,v,w;
bool operator< (const edge& B) const {return w>B.w;}
};
int n,m;
edge E[MAXM];
int f[MAXN];
int Fa(int x) {return f[x]==x ? x : f[x]=Fa(f[x]);}
void solve()
{
scanf("%d%d",&n,&m);
if (n==1) {
puts("0\n");
return;
}
for (int i=0; i<m; i++)
scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
sort(E,E+m);
for (int i=1; i<=n; i++)
f[i]=i;
for (int i=0; i<m; i++) {
int fu=Fa(E[i].u);
int fv=Fa(E[i].v);
f[fu]=fv;
if (Fa(1)==Fa(n)) {
printf("%d\n",E[i].w);
return;
}
}
}
int main()
{
int ttt;
scanf("%d",&ttt);
for (int ii=1; ii<=ttt; ii++) {
printf("Scenario #%d:\n",ii);
solve();
puts("");
}
return 0;
}
4. POJ-3268 Silver Cow Party
一个点是,他要求有向图中每个(点 p 到固定点 X ,再从 X 回到 P 的最短距离)的最大值,所以过去建一个图,回来建一个图,做两次迪杰斯特拉最短路,把最短路加起来就是最短来回距离了。
#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
#define INF (100200000)
void Dij(vector<int> &dis, vector<vector<pair<int,int> > > graph, int n, int X)
{
vector<bool> vis(n+2);
priority_queue<pair<int,int> > Q;
for (int i=1; i<=n; i++) {
vis[i]=0;
dis[i]=INF;
}
dis[X]=0;
Q.push(make_pair(0,X));
while (Q.size()) {
int u=Q.top().second;
Q.pop();
if (vis[u])
continue;
vis[u]=1;
for (int i=graph[u].size()-1; i>=0; i--) {
int v=graph[u][i].first;
int w=graph[u][i].second;
if (!vis[v] && dis[v]>dis[u]+w) {
dis[v]=dis[u]+w;
Q.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
int n,m,X;
scanf("%d%d%d",&n,&m,&X);
vector<vector<pair<int,int> > > graph1(n+2);
vector<vector<pair<int,int> > > graph2(n+2);
for (int i=0,uu,vv,ww; i<m; i++) {
scanf("%d%d%d",&uu,&vv,&ww);
graph1[uu].push_back(make_pair(vv,ww));
graph2[vv].push_back(make_pair(uu,ww));
}
vector<int> dis1(n+2);
vector<int> dis2(n+2);
Dij(dis1,graph1,n,X);
Dij(dis2,graph2,n,X);
int ans=0;
for (int i=1; i<=n; i++)
ans=max(ans,dis1[i]+dis2[i]);
printf("%d\n",ans);
return 0;
}
5. POJ-1860 Currency Exchange
SPFA 求正环
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 105
#define MAXM 105
int N,M,S;
double V;
struct edge {
int u,v;
double f,g;
edge(){};
edge(int uu,int vv,double ff,double gg): u(uu),v(vv),f(ff),g(gg) {}
};
vector<edge> graph[MAXN];
double dis[MAXN];
int cnt[MAXN];
bool inqueue[MAXN];
int main()
{
scanf("%d%d%d%lf",&N,&M,&S,&V);
for (int i=0; i<M; i++) {
int a,b;
double fab,gab,fba,gba;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&fab,&gab,&fba,&gba);
graph[a].push_back(edge(a,b,fab,gab));
graph[b].push_back(edge(b,a,fba,gba));
}
memset(dis,0,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(inqueue,0,sizeof(inqueue));
//SPFA
queue<int> Q;
Q.push(S);
inqueue[S]=1;
dis[S]=V; //dis 意思是从 S 到这,能拿到的最高钱数
cnt[S]=1;
while (Q.size()) {
int u=Q.front();
Q.pop();
inqueue[u]=0;
for (int i=graph[u].size()-1; i>=0; i--) {
int v=graph[u][i].v;
double f=graph[u][i].f;
double g=graph[u][i].g;
double tmp=(dis[u]-g)*f;
if (tmp>dis[v]) { //因为 dis 初始值为 0 , 所以不会出现欠钱
dis[v]=tmp;
if (!inqueue[v]) {
Q.push(v);
inqueue[v]=1;
if (++cnt[v]>N) { //入队次数多于 n 次,说明出现了正环
puts("YES");
return 0;
}
}
}
}
}
puts("NO");
return 0;
}
6.
7. POJ-1502 MPI Maelstrom
Floyd
#include <cstdio>
#define INF 999999999999999ll
#define MAXN 105
int n;
long long d[MAXN][MAXN];
int main()
{
char str[10];
scanf("%d",&n);
for (int i=1; i<n; i++) {
for (int j=0; j<i; j++) {
if (scanf("%lld",&d[i][j])!=1) {
scanf("%s",str);
d[i][j]=d[j][i]=INF;
}
else {
d[j][i]=d[i][j];
}
}
}
for (int i=0; i<n; i++)
d[i][i]=INF;
for (int k=0; k<n; k++)
for (int i=0; i<n; i++)
for (int j=i+1; j<n; j++)
if (d[i][j]>d[i][k]+d[k][j]) {
d[i][j]=d[i][k]+d[k][j];
d[j][i]=d[i][j];
}
long long ans=0;
for (int i=0; i<n; i++)
if (d[0][i]<INF && ans<d[0][i])
ans=d[0][i];
printf("%lld\n",ans);
return 0;
}
8. POJ-3660 Cow Contest
两个图,求每个点度数再判断一下就行了,数据小,随便做
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
vector<int> graph1[110];
vector<int> graph2[110];
bool vis[110];
void dfs(int X, int &cnt, vector<int> *graph)
{
vis[X]=1;
for (int i=graph[X].size()-1,v; i>=0; i--) {
v=graph[X][i];
if (!vis[v]) {
cnt++;
dfs(v,cnt,graph);
}
}
}
void solve()
{
int n,m,ans=0;
scanf("%d%d",&n,&m);
for (int i=1,a,b; i<=m; i++) {
scanf("%d%d",&a,&b);
graph1[a].push_back(b);
graph2[b].push_back(a);
}
for (int i=1; i<=n; i++) {
int cntin=0,cntout=0;
memset(vis,0,sizeof(vis));
dfs(i,cntin,graph1);
memset(vis,0,sizeof(vis));
dfs(i,cntout,graph2);
ans+=(cntin+cntout==n-1);
}
printf("%d\n",ans);
}
int main()
{
solve();
return 0;
}
9. POJ-2240 Arbitrage
单源最短路即可,令 dis 为最大倍率,看是否有大于一的回路