SCUTCODE.124 笔芯子序列 【最大流最小割】
来源:互联网 发布:4g网络设计思路 编辑:程序博客网 时间:2024/04/29 01:30
题目描述
对于一个n个数的正整数序列A,定义它的bx子序列为 p1,p2,⋯,pk,满足
1≤p1<p2< ... <pk≤n,Api≡0(mod Api−1),2≤i≤k
对于A,假设它的最长 bx 子序列长度为k,它的一个 bx子序列为
q1,q2,⋯,qt,使得删掉 Aq1,Aq2,...,Aqt
之后,A的最长 bx 子序列长度小于 k。
给定一个 n 个数的正整数序列 A,你需要求出它的最小 bx 子序列的长度。
输入格式
输入第一行一个整数 T,表示数据组数。
对于每组数据,第一行一个整数 n。
第二行n个整数,表示序列 A。
1≤T≤20
1≤n≤100
1≤Ai≤1000000000
输出格式
对每组数据,输出它的最小 bx 子序列的长度。
样例数据
输入
241 3 2 662 4 8 3 9 27
输出
12
若a[i]%a[j]==0,(j<i),连接一条从j到i的边,
再添加源汇点S,T,建立图G
跑一遍Floyd求最长路maxDis
对边(u,v),如果dis[s][u]+dis[v][t]+1==maxDis
那通过(u,v)边可能走出最长路,将(u,v)添加进图G'中
此时跑一遍最大流,即可得到G'的最小割:删除最少多少条边,使得最长路变短
但是原题要求的是删除多少个点
于是拆点跑最大流即可
#include<iostream>#include<cstdlib>#include<cstdio>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<ctime>#include<string.h>#include<math.h>#include<list>using namespace std;#define ll long long#define pii pair<int,int>const int inf = 1e9 + 7;const int N = 2*100+5;const int M = N*N*2;int a[N];struct Edge{ int fr,to,c,next;}edge[M];int head[N];int level[N];inline void addEdge(int k,int u,int v,int c){ edge[k].fr=u; edge[k].to=v; edge[k].c=c; edge[k].next=head[u]; head[u]=k;}bool bfs(int s,int t,int n){ deque<int>que; fill(level,level+n+1,-1); que.push_back(s); level[s]=0; while(!que.empty()){ int u=que.front(); if(u==t){ return true; } que.pop_front(); for(int i=head[u];i!=-1;i=edge[i].next){ if(edge[i].c>0&&level[edge[i].to]==-1){ level[edge[i].to]=level[u]+1; que.push_back(edge[i].to); } } } return false;}int dfs(int u,int t,int maxf){ if(u==t){ return maxf; } int sum=0; for(int i=head[u];i!=-1;i=edge[i].next){ Edge&e=edge[i]; if(e.c>0&&level[e.to]==level[u]+1){ int f=dfs(e.to,t,min(maxf-sum,e.c)); sum+=f; edge[i].c-=f; edge[i^1].c+=f; if(sum==maxf){ break; } } } level[u]=-1; return sum;}int dinic(int s,int t,int n){ int ans=0; while(bfs(s,t,n)){ ans+=dfs(s,t,2*inf); } return ans;}int dis[N][N];void floyd(int n){ for(int k=0;k<n;++k){ for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ if(dis[i][k]>0&&dis[k][j]>0){ dis[i][j]=max(dis[i][k]+dis[k][j],dis[i][j]); } } } }}vector<pii>vec;int main(){ //freopen("/home/lu/Documents/r.txt","r",stdin); //freopen("/home/lu/Documents/w.txt","w",stdout); int T; scanf("%d",&T); while(T--){ vec.clear(); int n; scanf("%d",&n); int s=2*n,t=s+1; memset(dis,0,sizeof(dis)); for(int i=0;i<n;++i){ scanf("%d",&a[i]); dis[s][i]=1; vec.push_back({s,i}); dis[i+n][t]=1; vec.push_back({i+n,t}); dis[i][i+n]=1; vec.push_back({i,i+n}); } for(int i=0;i<n;++i){ for(int j=0;j<i;++j){ if(a[i]%a[j]==0){ dis[j+n][i]=1; vec.push_back({j+n,i}); } } } floyd(t+1); int maxDis=dis[s][t]; fill(head,head+t+1,-1); int nume=0; for(int i=0;i<vec.size();++i){ int u=vec[i].first,v=vec[i].second; if(dis[s][u]+dis[v][t]+1==maxDis){ addEdge(nume++,u,v,1); addEdge(nume++,v,u,0); } } printf("%d\n",dinic(s,t,t+1)); } return 0;}
0 0
- SCUTCODE.124 笔芯子序列 【最大流最小割】
- 最大流/最小割
- 最大流最小割
- 最大流最小割
- 最大流最小割
- 最大流最小割
- 最大流最小割定理
- 最大流-最小割简介
- 最大流最小割定理
- poj3308 最大流最小割
- 最小割转最大流
- 最大流和最小割
- 最小割最大流记录
- hdu2435最大流最小割
- 最大流最小割定理
- 最大流最小割---FordFulkerson
- 最大流最小割算法
- 最大流最小割定理
- SOLR搜索引擎
- python 虚拟环境
- android Service使用AIDL来操作服务
- Java知识点(五)——集合框架
- 归并排序之递归排序9.4.2
- SCUTCODE.124 笔芯子序列 【最大流最小割】
- Flink Table & SQL API--动态表与Redo和Undo
- windows下nslookup命令
- properties Editor插件的安装
- IE和火狐的css兼容性问题
- StackoverflowAboutPython(1)—— Python中关键字yield有什么作用?
- Linux下查看tomcat占用端口
- C++ cin.clear()的使用:防止出现死循环
- 订单系统开发(仿淘宝和美团网) 之 项目总结(一)