【最短路】 HDOJ 1535 Invitation Cards

建正图,反图。然后用dijstra搜两边就行了。。

#include <iostream>  
#include <queue>  
#include <stack>  
#include <map>  
#include <set>  
#include <bitset>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
#include <climits>  
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 1000005
#define maxm 1000005
#define eps 1e-10
#define mod 998244353
#define INF 1e17
#define lowbit(x) (x&(-x))
#define mp mark_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid  
#define rson o<<1 | 1, mid+1, R  
typedef long long LL;
//typedef int LL;
using namespace std;
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();}
// head

struct Edge
{
	int u, v, c;
}edges[maxm];
struct node
{
	int x;
	LL d;
	bool operator < (const node &a) const {
		return a.d < d;
	}
}now, tmp;
priority_queue<node> q;
int h[maxn], next[maxm], v[maxm], cost[maxm];
int vis[maxn];
int n, m, cnt;
LL dis[maxn];

void read(void)
{
	scanf(n), scanf(m);
	//scanf("%d%d", &n, &m);
	for(int i = 0; i < m; i++) scanf(edges[i].u), scanf(edges[i].v), scanf(edges[i].c);
	//scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].c);
}
void init(void)
{
	cnt = 0;
	memset(h, -1, sizeof h);
	memset(vis, 0, sizeof vis);
	for(int i = 0; i <= n; i++) dis[i] = INF;
}
void addedges(int u, int vv, int c)
{
	next[cnt] = h[u], h[u] = cnt, v[cnt] = vv, cost[cnt] = c, cnt++;
}
void dijstra(int s)
{
	dis[s] = 0, tmp.x = s, tmp.d = 0, q.push(tmp);
	while(!q.empty()) {
		now = q.top(); q.pop();
		if(vis[now.x]) continue;
		vis[now.x] = 1;
		for(int e = h[now.x]; ~e; e = next[e])
			if(dis[v[e]] > dis[now.x] + cost[e]) {
				dis[v[e]] = dis[now.x] + cost[e];
				tmp.x = v[e], tmp.d = dis[v[e]];
				q.push(tmp);
			}
	}
}
void work(void)
{
	LL ans = 0;
	init();
	for(int i = 0; i < m; i++)
		addedges(edges[i].u, edges[i].v, edges[i].c);
	dijstra(1);
	for(int i = 1; i <= n; i++) ans += dis[i];
	init();
	for(int i = 0; i < m; i++)
		addedges(edges[i].v, edges[i].u, edges[i].c);
	dijstra(1);
	for(int i = 1; i <= n; i++) ans += dis[i];
	printf("%I64d\n", ans);
}
int main(void)
{
	int _;
	while(scanf("%d", &_)!=EOF) {
		while(_--) {
			read();
			work();
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值