比赛结束后看的一道题,是说给你m条边的两个点坐标代表m条路,每条路有一个权值,一个环的权值就是该环所经道路的权值之和,让你求出所有环中环的最小权值。环也就是起点和终点相同。
最多4000条边也就是
这里说一下Dijkstra算法的时间复杂度
先空着,等我会了再回来,网上大概是有两种题解,一种是暴力,枚举每一条边的两个点作为起点和终点,将该条边权值先改为INF,然后Dijkstra跑最短路,最后所有到终点的最短路加上被删去的边的权值求最小。注意该图是一个无向图,老是忘记正反两条边的我只能嘤嘤嘤。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn = 4000 + 10;
struct edge
{
int u,v,w;
edge(int from,int to,int ww):u(from),v(to),w(ww) {}
};
map<P,int> ma;
ll sum,d[maxn];
vector<int> g[maxn];
vector<edge> edges;
struct node
{
int v,w;
node(int to,int ww):v(to),w(ww) {}
bool operator <(const node & no)const
{
return w > no.w;
}
};
void init()
{
for(int i = 1; i < 4010; i++) g[i].clear();
edges.clear();
}
void addedge(int from,int to,int ww)
{
edges.push_back(edge(from,to,ww));
int t = edges.size();
g[from].push_back(t - 1);
}
void dijkstra(int s)
{
d[s] = 0;
priority_queue<node> q;
q.push(node(s,0));
while(!q.empty())
{
node now = q.top(); q.pop();
int u = now.v;
if(sum < now.w) break;
for(int i = 0; i < (int)g[u].size(); i++)
{
edge &e = edges[g[u][i]];
if(d[e.v] <= e.w) continue;
//printf("gg\n");
ll diss = d[u] + e.w;
//printf("%d\n",e.w);
//printf("%d %d %d %I64d\n",u,d[u],e.w,diss);
if(diss < d[e.v])
{
d[e.v] = diss;
q.push(node(e.v,d[e.v]));
}
// printf("%d\t%I64d\n",e.v,d[e.v]);
}
}
}
int main()
{
int T;
scanf("%d",&T);
for(int k = 1; k <= T; k++)
{
int num,x1,y1,x2,y2,co;
scanf("%d",&num);
init();
int id = 1;
ma.clear();
while(num--)
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&co);
if(!ma[P(x1,y1)]) ma[P(x1,y1)] = id++;
if(!ma[P(x2,y2)]) ma[P(x2,y2)] = id++;
addedge(ma[P(x1,y1)],ma[P(x2,y2)],co);
addedge(ma[P(x2,y2)],ma[P(x1,y1)],co);
}
sum = INF;
for(int i = 0; i < (int)edges.size(); i += 2)
{
// printf("%d\n",i);
// printf("%d %d %d\n",edges[i].u,edges[i].v,edges[i].w);
memset(d,INF,sizeof(d));
edge & e = edges[i];
// printf("%d %d %d\n",edges[i].u,edges[i].v,edges[i].w);
int dist = e.w;
e.w = INF;
edges[i + 1].w = INF;
dijkstra(e.u);
sum = min(sum,d[e.v] + dist);
// printf("%I64d %I64d\n",d[e.v],dist);
// printf("%d %d sum : %I64d\n",e.u,e.v,sum);
e.w = dist;
edges[i + 1].w = dist;
}
if(sum >= INF) sum = 0;
printf("Case #%d: %I64d\n",k,sum);
}
return 0;
}
第二种方法来日更新