[luogu4153]k小割

Subtask1(1-2)

暴力枚举割集并检验,时间复杂度为$o(m2^{m})$,可以通过

Subtask2(7-14)

记$a_{i},b_{i}$分别为$s,t$与$i$的边权,则有三种割边方案,代价分别为$a_{i},b_{i}$和$a_{i}+b_{i}$

(不妨假设$a_{i}\le b_{i}$)以$\sum a_{i}$为基础,记$d_{i}=\{b_{i}-a_{i},b_{i}\}$,并将其按$d_{i,0}$从小到大排序

用堆维护三元组$(S,k,p)$,分别表示权值和、当前位置和上一次是否选择$d_{k-1,0}$

初始加入$(0,1,0)$,每次取出堆顶的$(S,k,p)$,并在堆中加入$\begin{cases}(S+d_{k,0},k+1,1)\\(S+d_{k,1},k+1,0)\\(S-d_{k-1,0}+d_{k,0},k+1,1)&p=1\\(S-d_{k-1,0}+d_{k,1},k+1,0)&p=1\end{cases}$

(正确性基于方案生成方式唯一且存在&权值和单调不降,具体显然)

时间复杂度为$o(k\log k)$,可以通过

Subtask3(3-6,15-20)

用堆维护二元组$(E_{1},E_{2})$,表示满足$E_{1}\subseteq C$且$C\cap E_{2}=\empty$的次小割$C$

初始加入$(\empty,\empty)$,每次取出堆顶的$(E_{1},E_{2})$,并在堆中加入$(E_{1}\cup \{i\},E_{2})$和$(E_{1},E_{2}\cup\{i\})$

正确性类似前者,权值和单调性显然,下面考虑方案的生成方式:

1.唯一性,对过程建立二叉树,并对重复的两者分类讨论——

(1)不成祖先后代关系,此时取$lca$处的$i$,两者分别强制$i$在/不在$C$中,则割集必然不同

(2)成祖先后代关系,结合单调性,仅需保证加入的两者均不为$C$即可

记(对应)最小割为$C$,取$i$为$C$和$C_{0}$中状态不同的边,则$C$为最小割/不满足条件,即成立

2.存在性,归纳每个状态能拓展得到除最小割外的所有割集,即显然成立

关于次小割,其相比于最小割仅有两种情况:

1.包含最小割,即额外割掉一条$(割集\cup E_{2})$外的边

2.不包含最小割,枚举去掉的边$(x,y)$,即求$(S,x)$和$(y,T)$在残余网络上的最小割(取$\min$)

时间复杂度为$o(kn\cdot \max Flow(n,m)+k\log k)$,可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 55
  4 #define M 1505
  5 #define NN 300005
  6 #define ll long long
  7 int n,m,K,s,t;
  8 struct Edge{int x,y,z;}e[NN];
  9 namespace Subtask1{
 10     int vis[N];vector<int>v0,v[N];
 11     bool check(){
 12         if ((n>10)||(m>20))return 0;
 13         for(int i=1;i<=m;i++)
 14             if (e[i].z>65536)return 0;
 15         return 1;
 16     }
 17     void dfs(int k){
 18         if (vis[k])return;
 19         vis[k]=1;
 20         for(int i:v[k])dfs(i);
 21     }
 22     void main(){
 23         for(int S=0;S<(1<<m);S++){
 24             int sum=0;
 25             for(int i=1;i<=n;i++)vis[i]=0,v[i].clear();
 26             for(int i=1;i<=m;i++){
 27                 if ((S>>i-1)&1)sum+=e[i].z;
 28                 else v[e[i].x].push_back(e[i].y);
 29             }
 30             dfs(s);if (!vis[t])v0.push_back(sum);
 31         }
 32         sort(v0.begin(),v0.end());
 33         for(int i=0;i<K;i++){
 34             if (i==v0.size()){printf("-1\n");break;}
 35             printf("%d\n",v0[i]);
 36         }
 37     }
 38 };
 39 namespace Subtask2{
 40     int a[NN],b[NN];ll sum;
 41     pair<int,int>d[NN];
 42     struct Node{
 43         ll S;int k,p;
 44         bool operator < (const Node &n)const{
 45             return S>n.S;
 46         }
 47     }k;priority_queue<Node>q;
 48     bool check(){
 49         if (m!=(n<<1)-4)return 0;
 50         for(int i=1;i<=m;i++){
 51             if (e[i].x==s)a[e[i].y]=e[i].z;
 52             else b[e[i].x]=e[i].z;
 53         }
 54         for(int i=1;i<=n;i++)
 55             if ((i!=s)&&(i!=t)){
 56                 if ((!a[i])||(!b[i]))return 0;
 57             }
 58         return 1;
 59     }
 60     void main(){
 61         m=0;
 62         for(int i=1;i<=n;i++)
 63             if ((i!=s)&&(i!=t)){
 64                 if (a[i]>b[i])swap(a[i],b[i]);
 65                 sum+=a[i],d[++m]=make_pair(b[i]-a[i],b[i]);
 66             } 
 67         sort(d+1,d+m+1),q.push(Node{sum,1,0});
 68         for(int i=0;i<K;i++){
 69             if (q.empty()){printf("-1\n");break;}
 70             k=q.top(),q.pop();
 71             int j=k.k;printf("%lld\n",k.S);
 72             if (j<=m){
 73                 int x=d[j].first,y=d[j].second;
 74                 q.push(Node{k.S+x,j+1,1}),q.push(Node{k.S+y,j+1,0});
 75                 if (k.p){
 76                     k.S-=d[j-1].first;
 77                     q.push(Node{k.S+x,j+1,1}),q.push(Node{k.S+y,j+1,0});
 78                 }
 79             }
 80         }
 81     }
 82 };
 83 namespace Subtask3{
 84     int E,head[N],Head[N],d[N],D[N],visx[N],visy[N];queue<int>q;
 85     struct List{int nex,to,len;}edge[M<<1],Edge[M<<1];
 86     void add(int x,int y,int z){
 87         edge[E]=List{head[x],y,z},head[x]=E++;
 88         edge[E]=List{head[y],x,0},head[y]=E++;
 89     }
 90     bool bfs(){
 91         memset(d,-1,sizeof(d));
 92         d[s]=0,q.push(s);
 93         while (!q.empty()){
 94             int k=q.front();q.pop();
 95             for(int i=head[k];i!=-1;i=edge[i].nex)
 96                 if ((edge[i].len)&&(d[edge[i].to]<0)){
 97                     d[edge[i].to]=d[k]+1,q.push(edge[i].to);
 98                 }
 99         }
100         return d[t]>=0;
101     }
102     int dfs(int k,int s){
103         if (k==t)return s;
104         int ans=0;
105         for(int &i=head[k];i!=-1;i=edge[i].nex)
106             if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
107                 int p=dfs(edge[i].to,min(s,edge[i].len));
108                 edge[i].len-=p,edge[i^1].len+=p,s-=p,ans+=p;
109                 if (!s)return ans;
110             }
111         return ans;
112     }
113     int dinic(int S,int T){
114         swap(s,S),swap(t,T);
115         int ans=0;
116         while (bfs()){
117             ans+=dfs(s,1e9);
118             memcpy(head,Head,sizeof(head));
119             if (ans>=1e9){ans=1e9;break;}
120         }
121         swap(s,S),swap(t,T);
122         return ans;
123     }
124     struct Node{
125         int S,id;bool E1[M],E2[M];
126         bool operator < (const Node &n)const{
127             return S>n.S;
128         }
129         bool calc(){
130             int mn=1e8;S=0;
131             for(int i=1;i<=m;i++){
132                 edge[(i<<1)-1].len=0;
133                 if (E1[i])S+=e[i].z,edge[(i<<1)-2].len=0;
134                 else edge[(i<<1)-2].len=(E2[i] ? 1e9 : e[i].z);
135             }
136             S+=dinic(s,t);
137             memcpy(D,d,sizeof(d));
138             memset(visx,0,sizeof(visx));
139             memset(visy,0,sizeof(visy));
140             memcpy(Edge,edge,sizeof(edge));
141             for(int i=1;i<=m;i++)
142                 if ((!E1[i])&&(!E2[i])){
143                     if ((D[e[i].x]<0)||(D[e[i].y]>=0)){
144                         if (e[i].z<mn)mn=e[i].z,id=i;
145                     }
146                     else{
147                         if (!visx[e[i].x]){
148                             int x=dinic(s,e[i].x);
149                             if (x<mn)mn=x,id=i;
150                             memcpy(edge,Edge,sizeof(edge));
151                         }
152                         if (!visy[e[i].y]){
153                             int y=dinic(e[i].y,t);
154                             if (y<mn)mn=y,id=i;
155                             memcpy(edge,Edge,sizeof(edge));
156                         }
157                         visx[e[i].x]=visy[e[i].y]=1;
158                     }
159                 }
160             S+=mn;
161             return mn!=1e8;
162         }
163     }k;priority_queue<Node>Q;
164     void add(Node k){
165         if (k.calc())Q.push(k);
166     }
167     void main(){
168         memset(head,-1,sizeof(head));
169         for(int i=1;i<=m;i++)add(e[i].x,e[i].y,e[i].z);
170         memcpy(Head,head,sizeof(head));
171         K--,printf("%d\n",dinic(s,t));
172         add(Node{});
173         for(int i=0;i<K;i++){
174             if (Q.empty()){printf("-1\n");break;}
175             k=Q.top(),Q.pop();
176             printf("%d\n",k.S);
177             int x=k.id;k.E1[x]=1,add(k);
178             k.E1[x]=0,k.E2[x]=1,add(k);
179         }
180     }
181 };
182 int main(){
183     scanf("%d%d%d%d%d",&n,&m,&s,&t,&K);
184     for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
185     if (Subtask1::check()){
186         Subtask1::main();
187         return 0;
188     }
189     if (Subtask2::check()){
190         Subtask2::main();
191         return 0;
192     }
193     Subtask3::main();
194     return 0;
195 }
View Code

 

posted @ 2022-07-20 13:57  PYWBKTDA  阅读(78)  评论(0编辑  收藏  举报