Poj 3268 Silver Cow Party
题意:牛要去特定的牧场开舞会..其中要求去的路以及回来的最短路的和是最大的
思路:第一次利用dijstra求出从X到各点的最短距离,即为回来时的最短路。
然后所有的边反向,再进行一次dijstra求X到各点的最短路径。
第二次求出的最短路径也就是各点到X的最短路径,因为边已经反向,对于第二次从X到各点的最短路径正是
原图从各点到X的最短路径。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
const int INF = 0x3fffffff; //权值上限
const int MAXPT = 1002; //顶点数上限
const int MAXEG = 100000*2+10; //边数上限
//点存储1~n
class Dijkstra /*邻接表 + 优先队列 + Dijkstra求最短路*/
{
private:
int n,e,e1;
int dis[2][MAXPT], head[2][MAXPT];
int visit[MAXPT];
struct Node
{
int v,dis;
Node () {}
Node (int _v,int _dis)
{
v=_v;
dis=_dis;
}
bool operator < (const Node a) const
{
return dis>a.dis;
}
};
struct Edge
{
int v, w, next;
Edge () {}
Edge (int _v, int _next, int _w)
{
v=_v;
next=_next;
w=_w;
}
}edges[2][MAXEG];
public:
inline void init (int vx)
{
n = vx;
e = 0,e1=0;
memset(head[0],-1,sizeof(int) * (vx + 1));
memset(head[1],-1,sizeof(int) * (vx + 1));
}
inline void Add (int u, int v, int w)
{
edges[0][e] = Edge(v, head[0][u], w);
head[0][u] = e++;
}
inline void Add1 (int u, int v, int w)
{
edges[1][e1] = Edge(v, head[1][u], w);
head[1][u] = e1++;
}
void dijkstra (int flag,int src)
{
Node first, next;
priority_queue <Node> Q;
for (int i=0;i<=n;i++)
{
dis[flag][i] = INF;
visit[i] = false;
}
dis[flag][src]=0;
Q.push (Node(src, 0));
while (!Q.empty())
{
first = Q.top();
Q.pop();
visit[first.v] = true;
for (int i=head[flag][first.v] ; i!=-1 ; i=edges[flag][i].next)
{
if (visit[edges[flag][i].v])
continue;
next = Node(edges[flag][i].v, first.dis + edges[flag][i].w);
if (next.dis < dis[flag][next.v])
{
dis[flag][next.v] = next.dis;
Q.push(next);
}
}
}
}
int Deal (int x)
{
dijkstra (0,x);
dijkstra (1,x);
int ans=-1;
for (int i=1;i<=n;i++)
ans=max(ans,dis[0][i]+dis[1][i]);
return ans;
}
}ob;
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
int n,m,x;
while (~scanf("%d%d%d",&n,&m,&x))
{
ob.init(n);
while (m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ob.Add(u,v,w); //正图加边
ob.Add1(v,u,w); //反图加边
}
printf("%d\n",ob.Deal (x));
}
return 0;
}
题意:在一个有向图中,设原点为1,求所有点到1的最短路之和与1到所有点最短路之和的和。
思路:源点到其他点的最短距离可在原图中用spfa求出,其他点到源点最短距离可在逆图中用spfa求出。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
const int INF = 0x3fffffff; //权值上限
const int MAXPT = 1000005; //顶点数上限
const int MAXEG = 1000005; //边数上限
//点存储1~n
class Dijkstra /*邻接表 + 优先队列 + Dijkstra求最短路*/
{
private:
int n,e,e1;
int dis[2][MAXPT], head[2][MAXPT];
int visit[MAXPT];
struct Node
{
int v,dis;
Node () {}
Node (int _v,int _dis)
{
v=_v;
dis=_dis;
}
bool operator < (const Node a) const
{
return dis>a.dis;
}
};
struct Edge
{
int v, w, next;
Edge () {}
Edge (int _v, int _next, int _w)
{
v=_v;
next=_next;
w=_w;
}
}edges[2][MAXEG];
public:
inline void init (int vx)
{
n = vx;
e = 0,e1=0;
memset(head[0],-1,sizeof(int) * (vx + 1));
memset(head[1],-1,sizeof(int) * (vx + 1));
}
inline void Add (int u, int v, int w)
{
edges[0][e] = Edge(v, head[0][u], w);
head[0][u] = e++;
}
inline void Add1 (int u, int v, int w)
{
edges[1][e1] = Edge(v, head[1][u], w);
head[1][u] = e1++;
}
void dijkstra (int flag,int src)
{
Node first, next;
priority_queue <Node> Q;
for (int i=0;i<=n;i++)
{
dis[flag][i] = INF;
visit[i] = false;
}
dis[flag][src]=0;
Q.push (Node(src, 0));
while (!Q.empty())
{
first = Q.top();
Q.pop();
visit[first.v] = true;
for (int i=head[flag][first.v] ; i!=-1 ; i=edges[flag][i].next)
{
if (visit[edges[flag][i].v])
continue;
next = Node(edges[flag][i].v, first.dis + edges[flag][i].w);
if (next.dis < dis[flag][next.v])
{
dis[flag][next.v] = next.dis;
Q.push(next);
}
}
}
}
__int64 Deal (int x)
{
dijkstra (0,x);
dijkstra (1,x);
__int64 ans=0;
for (int i=1;i<=n;i++)
ans+=dis[0][i]+dis[1][i];
return ans;
}
}ob;
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
for (int Cas=1;Cas<=T;Cas++)
{
int n,m;
scanf("%d%d",&n,&m);
ob.init(n);
while (m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ob.Add(u,v,w); //正图加边
ob.Add1(v,u,w); //反图加边
}
printf("%I64d\n",ob.Deal (1));
}
return 0;
}