摧毁道路
题目描述:(暂不公开)
这道题的数据也是蛮有意思,有六十分是可以拿的。
但是自己写了六十分只拿到五十分。
主要是针对每个数据的弱点吧。
考场代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 3000;
const int INF = 0x3f3f3f3f;
inline int max(int a,int b) { return a > b ? a : b; }
inline int min(int a,int b) { return a < b ? a : b; }
inline void read(int &x)
{
char ch = getchar(); x = 0;
for(;ch < '0' || ch > '9';) ch = getchar();
for(;ch >= '0' && ch <= '9';) x = x * 10 + (ch ^ '0'), ch = getchar();
}
struct Edge{ int to,nxt,val,bz; } g[N << 1];
int last[N],cnt = 1;
int n,m,s1,t1,l1,s2,t2,l2,ans = -1;
int dis[N],dep[20],l,r,q[N << 2],vis[N],fa[N];
void add(int u,int v,int w) { g[++cnt] = (Edge){ v,last[u],w,1 }, last[u] = cnt; }
void Add_Edge(int u,int v,int w) { add(u,v,w), add(v,u,w); }
void work_dis()
{
memset(dis,INF,sizeof dis), dis[s1] = 0;
vis[q[l = r = 1] = s1] = 1;
for(;l <= r; ++ l)
{
for(int i = last[q[l]];i;i = g[i].nxt)
if(dis[g[i].to] > dis[q[l]] + g[i].val)
{
dis[g[i].to] = dis[q[l]] + g[i].val;
if(!vis[g[i].to]) vis[q[++r] = g[i].to] = 1;
}
vis[q[l]] = 0;
}
if(dis[t1] <= min(l1,l2)) ans = max(ans,m - dis[t1]);
}
void Dfs(int x,int ff)
{
for(int i = last[x];i;i = g[i].nxt)
if(g[i].to != ff) dis[g[i].to] = dis[x] + 1, fa[g[i].to] = x, Dfs(g[i].to,x);
}
void work_tree()
{
memset(dis,INF,sizeof dis); dis[1] = 0;
Dfs(1,0); int lca = 0,t = 0;
for(int i = s1;i;i = fa[i]) vis[i]++;
for(int i = t1;i;i = fa[i])
{
if(vis[i]) { lca = i; break; }
vis[i]++; ++t;
}
for(int i = s1;i != lca;i = fa[i]) ++t;
if(t > l1) return;
for(int i = fa[lca];i;i = fa[i]) vis[i] = 0; lca = 0;
for(int i = s2;i;i = fa[i]) vis[i]++; t = 0;
for(int i = t2;i;i = fa[i])
{
if(vis[i]) { lca = i; break; }
vis[i]++; ++t;
}
for(int i = s2;i != lca;i = fa[i]) ++t;
if(t > l2) return;
for(int i = fa[lca];i;i = fa[i]) vis[i] = 0;
int tot = 0;
for(int i = 1;i <= n; ++ i)
if(vis[i]) ++tot;
ans = max(ans,m - tot + 1);
}
int spfa(int st,int en,int limit)
{
memset(dis,INF,sizeof dis), dis[st] = 0;
vis[q[l = r = 1] = st] = 1;
for(;l <= r; ++ l)
{
for(int i = last[q[l]];i;i = g[i].nxt)
if(dis[g[i].to] > dis[q[l]] + g[i].val && g[i].bz)
{
dis[g[i].to] = dis[q[l]] + g[i].val;
if(!vis[g[i].to]) vis[q[++r] = g[i].to] = 1;
}
vis[q[l]] = 0;
}
if(dis[en] <= limit) return 1;
else return 0;
}
int check()
{
if(spfa(s1,t1,l1) && spfa(s2,t2,l2)) return 1;
else return 0;
}
void dfs(int x,int k)
{
if(k > m - max(l1,l2)) return;
if(x > cnt)
{
if(check())
ans = max(ans,k);
return;
}
dfs(x + 2,k);
g[x].bz = g[x ^ 1].bz = 0, dfs(x + 2,k + 1), g[x].bz = g[x ^ 1].bz = 1;
}
void work() { return; }
int main()
{
freopen("destroy.in","r",stdin);
freopen("destroy.out","w",stdout);
read(n), read(m); ans = -1;
for(int i = 1,u,v,w;i <= m; ++ i)
read(u), read(v), w = 1, Add_Edge(u,v,w);
read(s1), read(t1), read(l1);
read(s2), read(t2), read(l2);
if(n <= 15 && m <= 15) dfs(3,0);
else if(s1 == s2 && t1 == t2) work_dis();
else if(m == n - 1) work_tree();
else if(s1 == s2) work();
else printf("-1");
ans = ans == INF ? -1 : ans;
printf("%d",ans);
fclose(stdin); fclose(stdout);
return 0;
}
写了很多,但是基本上是模板。
然后这道题正解也不难。
我们可以预处理出每个点两两的最短距离。
这里是
的。
然后我们就可以再用
的时间来枚举路径
和
交集。
具体做法是枚举中间的一个点。
然后就可以算答案了。没有考场想到。
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 3010;
const int INF = 0x3f3f3f3f;
inline void read(int &x)
{
char ch = getchar(); x = 0;
for(;ch < '0' || ch > '9';) ch = getchar();
for(;ch >= '0' && ch <= '9';) x = x * 10 + (ch ^ '0'), ch = getchar();
}
struct Edge{ int to,nxt,val; } g[N << 1];
int last[N],cnt = 0,ans,l,r,mid,q[N << 2];
int n,m,s1,t1,l1,s2,t2,l2,dis[N][N];
void add(int u,int v,int w) { g[++cnt] = (Edge){ v,last[u],w }, last[u] = cnt; }
void Add_Edge(int u,int v,int w) { add(u,v,w), add(v,u,w); }
int main()
{
freopen("destroy.in","r",stdin);
freopen("destroy.out","w",stdout);
read(n), read(m);
for(int i = 1,u,v,w;i <= m; ++ i)
read(u), read(v), w = 1, Add_Edge(u,v,w);
read(s1), read(t1), read(l1), read(s2), read(t2), read(l2);
memset(dis,INF,sizeof dis);
for(int i = 1;i <= n; ++ i)
{
dis[i][i] = 0, q[l = r = 1] = i;
for(;l <= r; ++ l)
for(int j = last[q[l]];j;j = g[j].nxt)
if(dis[i][g[j].to] > dis[i][q[l]] + g[j].val)
q[++r] = g[j].to, dis[i][g[j].to] = dis[i][q[l]] + g[j].val;
}
if(dis[s1][t1] > l1 || dis[s2][t2] > l2) { printf("-1\n"); return 0; }
ans = m - dis[s1][t1] - dis[s2][t2];
for(int i = 1;i <= n; ++ i)
for(int j = 1;j <= n; ++ j)
{
if (dis[s1][i] + dis[i][j] + dis[j][t1] <= l1 && dis[s2][i] + dis[i][j] + dis[j][t2] <= l2)
{
int temp = dis[s1][i] + dis[s2][i] + dis[i][j] + dis[j][t1] + dis[j][t2];
if (m - temp > ans) ans = m - temp;
}
if (dis[s1][i] + dis[i][j] + dis[j][t1] <= l1 && dis[s2][j] + dis[i][j] + dis[i][t2] <= l2)
{
int temp = dis[s1][i] + dis[i][j] + dis[j][t1] + dis[s2][j] + dis[i][t2];
if (m - temp > ans) ans = m - temp;
}
}
printf("%d\n",ans);
fclose(stdin); fclose(stdout);
return 0;
}
太可惜了QAQ。