G - Pandaland HDU - 6005 (找最小环)
题目链接:https://cn.vjudge.net/contest/275153#problem/G
具体思路: 我们可以按照暴力的方法进行做 , 我们可以枚举每一条边,将这条边的权值设置为inf,然后再去跑最短路,起点是这条边的起点,如果说这条边的另一个点能够到达,并且总的路径花费小于inf,这就证明了有回路,然后再去从这些回路里面去找最小花费就可以了
AC代码:
#include<bits/stdc++.h>
using namespace std;
# define ll long long
const int maxn = 10000+100;
# define inf 0x3f3f3f3f
const int mod = 1e9;
map<pair<int,int>,int>vis;
int head[maxn],num,dis[maxn];
int ans;
struct node
{
int fr;
int to;
int cost;
int nex;
} edge[maxn];
struct point
{
int v;
int cost;
point() {}
point(int xx,int yy)
{
v=xx;
cost=yy;
}
friend bool operator < (point a,point b)
{
return a.cost>b.cost;
}
};
void init()
{
vis.clear();
num=0;
memset(head,-1,sizeof(head));
ans=inf;
}
void addedge(int fr,int to,int cost)
{
edge[num].to=to;
edge[num].fr=fr;
edge[num].nex=head[fr];
edge[num].cost=cost;
head[fr]=num++;
}
void krustra(int fr,int cost)
{
memset(dis,inf,sizeof(dis));
priority_queue<point>q;
dis[fr]=0;
q.push(point(fr,0));
while(!q.empty())
{
point tmp=q.top();
q.pop();
if(tmp.cost>ans)continue;
if(dis[tmp.v]+cost>ans)break;
for(int i=head[tmp.v]; i!=-1; i=edge[i].nex)
{
int u=edge[i].to;
if(dis[u]>dis[tmp.v]+edge[i].cost)
{
dis[u]=dis[tmp.v]+edge[i].cost;
q.push(point(u,dis[u]));
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
int Case=0;
while(T--)
{
int n;
init();
scanf("%d",&n);
int x1,y1,x2,y2,d;
int dfn=0;
for(int i=1; i<=n; i++)
{
scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&d);
if(vis[make_pair(x1,y1)]==0)
{
vis[make_pair(x1,y1)]=++dfn;
}
if(vis[make_pair(x2,y2)]==0)
{
vis[make_pair(x2,y2)]=++dfn;
}
addedge(vis[make_pair(x2,y2)],vis[make_pair(x1,y1)],d);
addedge(vis[make_pair(x1,y1)],vis[make_pair(x2,y2)],d);
}
for(int i=0; i<num; i+=2)
{
int tmp=edge[i].cost;
edge[i].cost=inf;
edge[i+1].cost=inf;//注意这是双向边,所以需要将相邻的两条边的权值都设置为inf
krustra(edge[i].fr,tmp);
ans=min(ans,dis[edge[i].to]+tmp);
edge[i].cost=tmp;
edge[i+1].cost=tmp;
}
printf("Case #%d: ",++Case);
if(ans==inf)printf("%d\n",0);
else printf("%d\n",ans);
}
return 0;
}