适合入门
POJ 2139
改错到怀疑人生结果发现存数组的时候把 j 写成了 i 。
另外还容易错的点是 牛的标记是从1开始的,要不存数组的时候就变成从1开始,要不就在输入牛标记存入时就要减去1
用到了Floyd-Warshall算法
多源最短路问题
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <utility>
#include <algorithm>
using namespacestd;
#define MAXN 310
#define MAXM 10001
#define INF 30000100
#define min(a,b) (a)<(b)?(a):(b)
int d[MAXN][MAXN];
int V;
int N,M,T;
int sum;
int t[MAXM];
void warshall_floyd()
{
for(int k=0;k<N;k++)
{
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
int main()
{
while(cin>>N>>M)
{
if(N==0&&M==0)
return0;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(i==j)
d[i][j]=0;
else
d[i][j]=INF;
}
}
for(int i=0;i<M;i++)
{
cin>>T;
for(int j=0;j<T;j++)
{
cin>>t[j];
t[j]--;
}
for(int j=0;j<T;j++)
{
for(int k=j+1;k<T;k++)
{
d[t[j]][t[k]]=1;
d[t[k]][t[j]]=1;
}
}
}
warshall_floyd();
int MIN=INF;
for(int i=0;i<N;i++)
{
sum=0;
for(int j=0;j<N;j++)
sum+=d[i][j];
if(sum<MIN)
MIN=sum;
}
sum=MIN*100/(N-1);
cout<<sum<<endl;
}
return 0;
}
POJ 3259
还是适合入门
至今觉得题目Two fields might be connected by more than one path. 这句话表达有问题,还以为输入的时候要判断两个点之间存较短的距离,
都打算用pair开始写了,然后发现可能是自己想太多了。还是找错误找到怀疑人生人生都用在找这些简单弱智的错误上了。
这道题目有一个坑就是路是双向的,要存两遍;虫洞是单向的,存一遍就好。只要判断存在负圈,即可输出YES。
还有不知道为什么MAXN要开到6000,不然会RE。
用到了Bellman-Ford算法,因为如果图中不存在负圈,那么最短路不会经过同一个顶点两次(即|V|-1 条边)。相反,如果存在负圈,那么第|N|次循环也会更新d的值,所以只要第|N|次循环更新了d的值,就存在负圈。
#include <iostream>
#include <algorithm>
using namespacestd;
#define MAXV 510
#define MAXM 6000
#define INF 50000000
struct edge
{
int from,to,cost;
}es[MAXM];
int d[MAXV];
int F,N,M,W;
int f,t,c,w;
int top;
int bellman()
{
int i,j;
for(i=1;i<=N;i++)
d[i]=INF;
d[1]=0;
for(i=1;i<=N;i++)
{
for(j=1;j<=top;j++)
{
edge e=es[j];
if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.cost)
{
d[e.to]=d[e.from]+e.cost;
if(i==N)
return0;
}
}
}
return1;
}
int main()
{
cin>>F;
while(F--)
{
cin>>N>>M>>W;
top=1;
while(M--)
{
cin>>f>>t>>c;
es[top].from=f;
es[top].to=t;
es[top].cost=c;
top++;
es[top].from=t;
es[top].to=f;
es[top].cost=c;
top++;
}
while(W--)
{
cin>>es[top].from>>es[top].to>>w;
es[top].cost=(-1)*w;
top++;
}
if(bellman())
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return0;
}
POJ 3268
因为时间有点紧,觉得自己徒手打有难度
所以借鉴了网上的解题报告
http://www.hankcs.com/program/cpp/poj-3268-silver-cow-party.html
用到了Dijkstra算法,用优先队列较快找到最小值节省时间复杂度
思路很巧妙,把图反着也存一遍,那么就是从确定的一个点出发,求最短路径之和的最大值。
因为排序在+1的基础上不会处理,所以还是把农场-1存储了。
还有大神的排序方法也收下了
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define MAXV 1010
#define MAXE 100100
#define INF 100000000
struct edge
{
int to,cost;
edge(){}
edge(int to,int cost):to(to),cost(cost){}
};
typedef pair<int,int> P;
//********
vector<vector<edge>> G(MAXV);
vector<vector<edge>> RG(MAXV);
int d[MAXV];
int rd[MAXV];
int V,E;
void dijkstra(int s)
{
priority_queue<P,vector<P>,greater<P>>que;
fill(d,d+V,INF);
d[s]=0;
que.push(P(0,s));
while(!que.empty())
{
P p=que.top();
que.pop();
int v=p.second;
if(d[v]<p.first) continue;
for(int i=0;i<G[v].size();i++)
{
edge e=G[v][i];
if(d[e.to]>d[v]+e.cost)
{
d[e.to]=d[v]+e.cost;
que.push(P(d[e.to],e.to));
}
}
}
}
int main()
{
int M,X;
while(cin>>V>>M>>X)
{
X--;
while(M--)
{
int A,B,T;
cin>>A>>B>>T;
A--;B--;
G[A].push_back(edge(B,T));
//在vector尾部加入一个数据
RG[B].push_back(edge(A,T));
}
dijkstra(X);
G=RG;
//********
memcpy(rd,d,sizeof(d));
dijkstra(X);
for(int i=0;i<V;i++)
d[i]+=rd[i];
//sort(d,d+V);
//cout<<d[V-1]<<endl;
//V++;
cout << *max_element(d,d+V) << endl;
}
return 0;
}