这一题看起来很水,结果被坑了大半天。><
解法就是把所有的点当做起点,求一次最短路。再看这些最短路上有哪些边,这些边就是就是efficient的。
最开始我是用一个pre对最短路上的每个点记录其parent node,然后循环从终点推到起点就可以得出这一条最短路上有哪些边。这么做有一个问题,如果st to ed存在多条最短路,pre数组就会被覆盖掉,然后只会记录一条最短路上的边。感觉如果对每一个node内一个pre vector,然后dfs找出所有的最短路也行吧。正解是如果dis[i]+cost[i][j]=dis[j]那么边(i,j)就是在i to j的最短路上。其中dis[i]是st to i的最短路距离,cost是两个点之间的weight。
另外,这一题中两个office之间可能有多条road,这些road的cost可能相同也可能不同。所以就不能用邻接矩阵存图,因为这样两个office之间只会记录一条边。改成邻接表存图就不会有这个问题。我用邻接矩阵开始过了小数据,大数据incorrect。还以为是溢出了,最后是通过看large input data+对拍找出来的。/(ㄒoㄒ)/~~
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
//2016 Round A Problem C. gCampus
int T;
const int maxn=110;
int M;
int N;
pair<int,int>road[10010];
long long dis[maxn];//arriving time=S+distance
const long long INF=1e18;
bool vis[maxn];
bool efficient[10010];
//int edgeidx[maxn][maxn];
class node
{
public:
int neighbor;
int cost;
int index;
node()
{
neighbor=0;
cost=0;
index=0;
}
node(int n,int c,int i)
{
neighbor=n;
cost=c;
index=i;
}
};
vector<node>mp[maxn];
class ComparisonClass
{
public:
bool operator()(pair<long long,int>a,pair<long long,int>b)
{
if(a.first==b.first)
{
return a.second>b.second;//second is index
}
return a.first>b.first;//first is distance
}
};
void shortest(int st)
{
//memset(dis,0x3f,sizeof(dis));
for(int i=0;i<N;i++)
{
dis[i]=INF;
}
memset(vis,false,sizeof(vis));
// memset(pre,0,sizeof(pre));
dis[st]=0;
//pre[st]=-1;
priority_queue<pair<long long,int>,vector<pair<long long,int> >,ComparisonClass> que;
que.push(make_pair(0,st));
while(!que.empty())
{
pair<long long,int>now=que.top();
vis[now.second]=true;
que.pop();
// cout<<"cur "<<now.second<<endl;
for(int i=0;i<mp[now.second].size();i++)
{
int neigh=mp[now.second][i].neighbor;
//if(mp[now.second][i]==0) continue;
if(vis[neigh]==true) continue;
if(dis[neigh]>now.first+mp[now.second][i].cost)
{
dis[neigh]=now.first+mp[now.second][i].cost;
//pre[i]=now.second;
//cout<<"update "<<i<<" "<<pre[i]<<endl;
// if(st==0&&i==2)
// {
// cout<<now.second<<" "<<now.first<<" "<<mp[now.second][i]<<endl;
// }
pair<long long,int>tmp=make_pair(dis[neigh],neigh);
que.push(tmp);
}
}
}
// if(st!=0) return;
// for(int i=0;i<N;i++)
// {
// cout<<dis[i]<<endl;
cout<<"ed "<<i<<" "<<dis[i]<<endl;
// }
}
//void findallroads(int st)
//{
// for(int ed=0;ed<N;ed++)
// {
// if(st==ed) continue;
// int node=ed;
// while(pre[node]!=-1)
// {
// //cout<<node<<" "<<pre[node]<<endl;
// used.insert(make_pair(min(node,pre[node]),max(node,pre[node])));
// node=pre[node];
// }
// }
//}
void findallroads()
{
for(int i=0;i<N;i++)
{
for(int j=0;j<mp[i].size();j++)
{
int neigh=mp[i][j].neighbor;
if(dis[i]+mp[i][j].cost==dis[neigh])
{
efficient[mp[i][j].index]=true;
//used.insert(make_pair(min(i,j),max(i,j)));
}
}
}
}
int main()
{
freopen("C-large-practice.in","r",stdin);
// freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
scanf("%d %d",&N,&M);
memset(mp,0,sizeof(mp));
memset(efficient,false,sizeof(efficient));
// used.clear();
for(int i=0;i<M;i++)
{
int U=0;
int V=0;
int C=0;
scanf("%d %d %d",&U,&V,&C);
mp[U].push_back(node(V,C,i));
mp[V].push_back(node(U,C,i));
// if(mp[U][V]==0)//(U,V) may have multiple input cost, use adjacent vector instead
// {
// mp[U][V]=C;
// edgeidx[U][V]=i;
// }
// else
// {
// cout<<U<<" "<<V<<" "<<C<<" "<<mp[U][V]<<endl;
// if(C<mp[U][V])
// {
// mp[U][V]=C;
// edgeidx[U][V]=i;//what if (U,V) is connected by two roads with same cost?
// }
// //mp[U][V]=min(mp[U][V],C);
// }
// if(mp[V][U]==0)
// {
// mp[V][U]=C;
// edgeidx[V][U]=i;
// }
// else
// {
// if(C<mp[V][U])
// {
// mp[V][U]=C;
// edgeidx[V][U]=i;
// }
// //mp[V][U]=min(mp[V][U],C);
// }
// if(U==0&&V==2) cout<<U<<" "<<V<<" "<<mp[U][V]<<endl;
// if(U==2&&V==0) cout<<U<<" "<<V<<" "<<mp[U][V]<<endl;
//road[i]=make_pair(min(U,V),max(U,V));
//set.insert(make_pair(min(U,V),max(U,V)));
}
//cout<<N<<endl;
printf("Case #%d:\n",ca);
for(int i=0;i<N;i++)
{
//cout<<i<<endl;
shortest(i);
findallroads();
}
//int cnt=0;
for(int i=0;i<M;i++)
{
if(efficient[i]==false)
{
printf("%d\n",i);
}
// if(used.find(road[i])==used.end())
// {
// //ineff[cnt++]=i;
// printf("%d\n",i);
// }
}
}
return 0;
}