货车运输这道题我觉得还是比较有难度,不好直接想出正解,我最开始就是直接用并查集判定然后暴力找,在网上只有10分。
//以下是暴力
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 10005
#define MAXM 50005
#define MAXP 30005
inline void GET(int &n)
{
n = 0; char c;
do c = getchar(); while(c > '9' || c < '0');
while(c>='0' && c<='9'){n = n * 10 + c - '0'; c = getchar();}
}
struct P
{
int s, t, i;
bool operator < (const P rhs) const
{
return s < rhs.s;
}
}op[MAXP];
struct node
{
int v, w;
node *next;
}Edge[MAXN*2], *Adj[MAXN], *Mcnt = Edge;
void Addedge(int u, int v, int w)
{
node *t = ++Mcnt;
t->v = v;
t->w = w;
t->next = Adj[u];
Adj[u] = t;
}
int fa[MAXN], w[MAXN], n, m, p, ans[MAXP];
int rt(int x)
{
if(fa[x] && fa[x] != x) return fa[x] = rt(fa[x]);
return x;
}
void dfs(int u, int c)
{
w[u] = c;
int C;
for(node *p = Adj[u]; p; p = p->next)
{
C = min(p->w, c);
if(w[p->v] < C) dfs(p->v, C);
}
}
int main()
{
int t1, t2, t3;
GET(n);GET(m);
for(int i = 1; i <= m; i ++)
{
GET(t1);GET(t2);GET(t3);
Addedge(t1, t2, t3);
Addedge(t2, t1, t3);
if(rt(t1) != rt(t2) || rt(t1) == 0)fa[rt(t1)] = rt(t2);
}
GET(p);
for(int i = 1; i <= p; i ++)
{
GET(t1);GET(t2);
op[i].s = min(t1, t2);
op[i].t = max(t1, t2);
op[i].i = i;
}
sort(op + 1, op + p + 1);
int pre = -1;
for(int i = 1; i <= p; i ++)
{
if(rt(op[i].s) != rt(op[i].t))
{
ans[op[i].i] = -1;
continue;
}
if(pre != op[i].s)
{
memset(w, -1, sizeof w);
w[op[i].s] = 0x7f7f7f7f;
dfs(op[i].s, 0x7f7f7f7f);
pre = op[i].s;
}
ans[op[i].i] = w[op[i].t];
}
for(int i = 1; i <= p; i ++)
printf("%d\n", ans[i]);
return 0;
}
后来才知道要用最大生成树去掉没有价值的边,然后我又写了一个最大生成树+暴力找路径最小边的,得到了30分
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 10005
#define MAXM 50005
#define MAXP 30005
inline void GET(int &n)
{
n = 0; char c;
do c = getchar(); while(c > '9' || c < '0');
while(c>='0' && c<='9'){n = n * 10 + c - '0'; c = getchar();}
}
struct P
{
int s, t, v;
bool operator < (const P rhs) const
{
return v > rhs.v;
}
}a[MAXP];
struct node
{
int v, w;
node *next;
}Edge[MAXN*2], *Adj[MAXN], *Mcnt = Edge;
void Addedge(int u, int v, int w)
{
node *t = ++Mcnt;
t->v = v;
t->w = w;
t->next = Adj[u];
Adj[u] = t;
}
int fa[MAXN], n, m, p;
int rt(int x)
{
if(fa[x] && fa[x] != x) return fa[x] = rt(fa[x]);
return x;
}
bool vis[MAXN][2];
int w[MAXN];
struct Y
{
int a;
bool f;
Y(){}
Y(int b,bool g){a = b; f = g;}
};
int BFS(int r1, int r2)
{
queue<Y> q;
q.push(Y(r1, 0));
q.push(Y(r2, 1));
memset(w, 0, sizeof w);
memset(vis, 0, sizeof vis);
vis[r1][0] = vis[r2][1] = 1;
w[r1] = w[r2] = 0x7f7f7f7f;
while(!q.empty())
{
int u = q.front().a;
bool f = q.front().f;
q.pop();
for(node *p = Adj[u]; p; p = p->next)
{
if(!vis[p->v][f])
{
if(vis[p->v][!f]) return min(min(w[p->v], w[u]), p->w);
w[p->v] = min(w[u], p->w);
q.push(Y(p->v, f));
vis[p->v][f] = 1;
}
}
}
return -1;
}
int main()
{
int t1, t2, t3;
GET(n);GET(m);
for(int i = 1; i <= m; i ++)
{
GET(t1);GET(t2);GET(t3);
a[i].s = t1, a[i].t = t2, a[i].v = t3;
}
sort(a+1, a+m+1);
int tot = 0;
for(int i = 1; i <= m; i ++)
{
t1 = a[i].s, t2 = a[i].t, t3 = a[i].v;
int p = rt(t1), q = rt(t2);
if(p != q){
fa[p] = q;
Addedge(t1, t2, t3);
Addedge(t2, t1, t3);
tot ++;
if(tot == n - 1) break;
}
}
GET(p);
for(int i = 1; i <= p; i ++)
{
GET(t1);GET(t2);
int p = rt(t1), q = rt(t2);
if(p != q){puts("-1");continue;}
int tp = BFS(t1, t2);
printf("%d\n", tp);
}
return 0;
}
过后,对于每一个连通块用dfs把无根树变成了有根树就非常快了,得分100,耗时44ms
#include<cstdio>
#include<ctime>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 10005*2
#define MAXM 50005*2
#define MAXP 30005*2
inline int min(const int &a, const int &b){return a<b?a:b;}
inline void GET(int &n)
{
n = 0; char c;
do c = getchar(); while(c > '9' || c < '0');
while(c>='0' && c<='9'){n = n * 10 + c - '0'; c = getchar();}
}
struct P
{
int s, t, v;
bool operator < (const P rhs) const
{
return v > rhs.v;
}
}a[MAXP];
struct node
{
int v, w;
node *next;
}Edge[MAXN*2], *Adj[MAXN], *Mcnt = Edge;
void Addedge(int u, int v, int w)
{
node *t = ++Mcnt;
t->v = v;
t->w = w;
t->next = Adj[u];
Adj[u] = t;
}
int fa[MAXN], n, m, p;
int rt(int x)
{
if(fa[x] && fa[x] != x) return fa[x] = rt(fa[x]);
return x;
}
int pre[MAXN], dep[MAXN], v[MAXN];
bool vis[MAXN];
void dfs(int u)
{
vis[u] = 1;
for(node *p = Adj[u]; p; p = p->next)
if(!vis[p->v])
{
pre[p->v] = u;
v[p->v] = p->w;
dep[p->v] = dep[u] + 1;
dfs(p->v);
}
}
int Val(int t1, int t2)
{
int mn1 = 0x7f7f7f7f, mn2 = 0x7f7f7f7f;
if(dep[t1] < dep[t2]) swap(t1, t2);
while(dep[t1] > dep[t2])
{
mn1 = min(mn1, v[t1]);
t1 = pre[t1];
}
while(t1 != t2)
{
mn1 = min(mn1, v[t1]);
t1 = pre[t1];
mn2 = min(mn2, v[t2]);
t2 = pre[t2];
}
return min(mn1, mn2);
}
int main()
{
int t1, t2, t3;
GET(n);GET(m);
for(int i = 1; i <= m; i ++)
{
GET(t1);GET(t2);GET(t3);
a[i].s = t1, a[i].t = t2, a[i].v = t3;
}
sort(a+1, a+m+1);
int tot = 0;
for(int i = 1; i <= m; i ++)
{
t1 = a[i].s, t2 = a[i].t, t3 = a[i].v;
int p = rt(t1), q = rt(t2);
if(p != q){
fa[p] = q;
Addedge(t1, t2, t3);
Addedge(t2, t1, t3);
tot ++;
if(tot == n - 1) break;
}
}
GET(p);
for(int i = 1; i <= n; i ++)
if(!vis[i])
dfs(i);
for(int i = 1; i <= p; i ++)
{
GET(t1);GET(t2);
int p = rt(t1), q = rt(t2);
if(p != q){puts("-1");continue;}
int tp = Val(t1, t2);
printf("%d\n", tp);
}
return 0;
}