0%

计蒜之道复赛 补题

https://nanti.jisuanke.com/t/11217 比赛时候一眼就看出了,肯定是flyod的变种...然而因为智商问题,并看不出来是怎么变种的... 因为这个题最傻逼的算法是一个四维的floyd,标算就是将第一维分治。 因为floyd的第一维对结果没有任何影响,所以就递归的每次加入一半的点就可以了 虽然所有结论都知道...但是这个算法却想不出来...所以还是挺神的...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include<bits/stdc++.h>
using namespace std;
int n;
int e[310][310]={};
long long ans=0ll;
void ff(int x,int y,int e[310][310])
{
if(x==y)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=x&&j!=x) ans+=(long long)e[i][j];
}
}
return;
}
int mid=(x+y)/2;
int u[310][310]={};
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
u[i][j]=e[i][j];
}
}
for(int k=x;k<=mid;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(u[i][j]==-1&&u[i][k]!=-1&&u[k][j]!=-1)
{
u[i][j]=u[i][k]+u[k][j];
}
else if(u[i][k]!=-1&&u[k][j]!=-1)
{
u[i][j]=min(u[i][j],u[i][k]+u[k][j]);
}
}
}
}
ff(mid+1,y,u);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
u[i][j]=e[i][j];
}
}
for(int k=mid+1;k<=y;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(u[i][j]==-1&&u[i][k]!=-1&&u[k][j]!=-1)
{
u[i][j]=u[i][k]+u[k][j];
}
else if(u[i][k]!=-1&&u[k][j]!=-1)
{
u[i][j]=min(u[i][j],u[i][k]+u[k][j]);
}
}
}
}
ff(x,mid,u);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>e[i][j];
}
}
ff(1,n,e);
cout<<ans;
return 0;
}

https://nanti.jisuanke.com/t/11215 经典的姿势,把一个点拆成一个入点和一个出点,通过控制流量为1,来保证每个点只经过一次。 源点为mid,汇点为a和b 注意,mid拆点之后连的边的流量应该为2...这里调了好长时间...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include<bits/stdc++.h>
#define maxn 210
using namespace std;
int n,m;
struct Edge{
int from,to,cap,flow;
};
struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int an[maxn];
int u=0;
void AddEdge(int from,int to,int cap)
{
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0});
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=0;i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x==t||a==0) return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
this->s=s;
this->t=t;
int flow=0;
while(bfs())
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,2147483600);
}
return flow;
}
void ff(int x,int h)
{
if(1<=x&&x<=h)
{
u++;
an[u]=x;
}
vis[x]=1;
for(int i=0;i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap==e.flow&&e.cap)
{
ff(e.to,h);
}
}
}
void ans(int a,int b,int h)
{
memset(vis,0,sizeof(vis));
ff(s,h);
bool vv[maxn]={};
int nu=0;
bool bj=0;
for(int i=u;i>=1;i--)
{
if(an[i]==a) bj=1;
if(an[i]==b) bj=0;
if(bj==1) cout<<an[i]<<" ",vv[i]=1,nu++;
}
for(int i=1;i<=u;i++)
{
if(vv[i]==0)
{
cout<<an[i];
nu++;
if(nu!=u) cout<<" ";
}
}
cout<<endl;
}
};
void work()
{
Dinic dinic;
int a,b,mid;
int x,y;
cin>>n>>m;
cin>>a>>b>>mid;
for(int i=1;i<=n;i++)
{
if(i!=mid) dinic.AddEdge(i,i+n,1);
else dinic.AddEdge(i,i+n,2);
}
dinic.AddEdge(a+n,0,1);
dinic.AddEdge(b+n,0,1);
for(int i=1;i<=m;i++)
{
cin>>x>>y;
dinic.AddEdge(x+n,y,1);
dinic.AddEdge(y+n,x,1);
}
int o=dinic.Maxflow(mid,0);
dinic.ans(a,b,n);
}
int main()
{
int T;
cin>>T;
while(T--) work();
return 0;
}