题目链接:杭电 : http://acm.hdu.edu.cn/showproblem.php?pid=6386
Atcode: https://arc061.contest.atcoder.jp/tasks/arc061_c
这个代码打死T杭电,没加输入挂,也没有花Vector,原来堆优化的假算法那种方法在杭电AC了,但是在ATcode是过不去的,所以就有重新写了一个拆点的,但是Atcode过了,杭电T到怀疑了。
就按照在Atcode过的来说一下我的思路吧,本来杭电过的代码去了Atcode WA大概12组实例,然后百度了下说是拆点建一个新图跑最短路就行了。
第一次做拆点的题,整理下对于这道题拆点的思路,本来是(U,V,C)这样的一个三元组的关系,本来有公司和路径2个关系,现在将他们拆开,拆成公司的一个对应关系,这样就变成一个不定点了,然后建立(u,c) (v,c)的双向边,权值为1,代表这两个点在这个公司的通路网内,可以再u,v上车,然后对于(u,c) 和 (v,c) 这个关系在建立一个双向边,表示这个公司内部可以通车,这样的话就是不花钱的喽,举个例子
3 2
1 2 1
2 3 1
这样建立的边有 (1,4,1)(4,1,1) (2,5,1)(5,2,1)(4,5,0)(5,4,0) 和 (2,5,1) (5,2,1) (3,6,1) (6,3,1)(5,6,0)(6,5,0)这样从1上车通过1公司的内部网格到达(1,4,1) (4,5,0) 然后(5,6,0) (6,3,1) 这样就结束了这个网格,权值最后是2,因为把上车和下车都是权值为1,所以最后输出dist[n] / 2
试了试spfa和堆优化的Dijkstra时间差不多,可能没有去卡这个东西吧。
对于拆点理解可能不太好理解,可以画下图自己感受下。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<ll,ll>Pa;
const long long INF = 1ll<<62;
const int maxn = 5e5+10;
ll n,m,cnt;
map<ll,ll>Ma[maxn];//标记
vector<Pa>V[maxn];//存放pair关系
int vis[maxn];
ll dist[maxn];
struct node{
ll dist;
int id;
bool operator < (const node& b) const
{
return dist > b.dist;
}
};
int getid(int u,int v)//返回编号
{
if(Ma[u][v]==0)
Ma[u][v]=++cnt;
return Ma[u][v];
}
inline void spfa()
{
for(int i=0;i<=cnt;i++)
{
vis[i]=0;
dist[i]=INF;
}
node temp;
temp.dist=0;
temp.id=1;
priority_queue<node> q;
q.push(temp);
dist[1]=0;
while(!q.empty())
{
node u=q.top();
q.pop();
if(vis[u.id]==1)
continue;
vis[u.id]=1;
for(int i=0;i<V[u.id].size();i++)
{
int v=V[u.id][i].first;
int Valu=V[u.id][i].second;
if(dist[v] > dist[u.id]+Valu)
{
dist[v]=dist[u.id]+Valu;
node Temp;
Temp.dist=dist[v];
Temp.id=v;
q.push(Temp);
}
}
}
if(dist[n]==INF)
printf("-1\n");
else
printf("%lld\n",dist[n]/2);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<=n;i++)
Ma[i].clear();
for(int i=0;i<=n;i++)
V[i].clear();
cnt=n;//从n+1开始记录编号
for(int i=0;i<m;i++)
{
int u,v,id;
scanf("%d%d%d",&u,&v,&id);
int uid=getid(u,id);
int vid=getid(v,id);
V[u].push_back(Pa(uid,1));
V[uid].push_back(Pa(u,1));
V[v].push_back(Pa(vid,1));
V[vid].push_back(Pa(v,1));
V[vid].push_back(Pa(uid,0));
V[uid].push_back(Pa(vid,0));
}
spfa();
}
return 0;
}