怎么发一次格式抽一次
T1
打表发现答案小于n
考虑求出S,T的最小割,并且提取出在S这一边和在T这一边的点集
考虑S'属于S这一边的点集,T'属于T这一边的点集,那么S'和T'的最小割可以用其他两个点代替
借助bzoj2229黄学长的一句话:
注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z、X∩W、Y∩Z、Y∩W这四项不可能均非空。也就是说,最小割不可能相互跨立。
这个蕴含了,最多一共有N-1个不同的s-t最小割。只需把这些割找出来即可。
寻找的方法:首先,在V中任意找两个点a,b,求最大流,把V划分为割X-Y,之后对X、Y分别递归地进行划分。这样就能得到N-1个割了。
那么我们可以分治求最小割,这样求得的最小割一定能够代表所有的最小割
T2
第一种:考场上YY出来的,因为太懒所以没写
首先求凸包,求出凸包上每一个点所能到达的最远点,push到堆中
对全局维护一个堆,每次弹出最大值,然后讲两个点的次远点在kd树中找出来
找出来的复杂度是sqrt(n)的,外加二份答案,共k次,总复杂度k*sqrt(n)*log(没有代码)
第二种
还是求出凸包和每一个点所能到达的最远点,每次拿出堆中的时候暴力扫n个点,强行插入次远的点
所以下面这个是nklog的。也能过
T3
傻逼数位dp
dp[当前位数][是否有8][是否有4][上一位][连续几位][已经有没有3位连续的][是否达到上限]
dfs一遍记忆化转移就好
顺便说一句,函数记得return啊!!!关键是小数据还是对的调崩我了
代码
T1
//Copyright(c)2016 liuchenrui
#include
#define short unsigned short
#define inf 1000000000
using namespace std;
template
inline void splay(T &v){
v=0;char c=0;T p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
struct Edge{
short to,next;int flow;
}edge[100010];
short first[851],size;
short deep[851],dl[851];
void addedge(short x,short y,int z){
size++;
edge[size].to=y;
edge[size].next=first[x];
first[x]=size;
edge[size].flow=z;
}
void add(short x,short y,int z){
addedge(x,y,z),addedge(y,x,0);
}
short aim;
int dfs(short now,int flow){
if(now==aim)return flow;
int F=0;
for(short u=first[now];u&&flow;u=edge[u].next){
if(deep[edge[u].to]==deep[now]+1&&edge[u].flow){
int tmp=dfs(edge[u].to,min(flow,edge[u].flow));
F+=tmp;edge[u].flow-=tmp;edge[u^1].flow+=tmp;flow-=tmp;
}
}
if(!F)deep[now]=-5;
return F;
}
bool bfs(short S,short T){
memset(deep,0,sizeof(deep));
dl[1]=S;deep[S]=1;
short head=0,tail=1;
while(head!=tail){
head++;
for(int u=first[dl[head]];u;u=edge[u].next){
if(!deep[edge[u].to]&&edge[u].flow){
dl[++tail]=edge[u].to;
deep[edge[u].to]=deep[dl[head]]+1;
}
}
}
return deep[T];
}
int maxflow(short S,short T){
int ret=0;aim=T;
while(bfs(S,T)){
ret+=dfs(S,inf);
}
return ret;
}
short fr[8600],to[8600];
int fl[8600];
int ans[1000010];
short cnt,n,m,p[851];
void rebuild(){
memset(first,0,sizeof first);
size=1;
for(int k=1;k<=m;k++){
add(fr[k],to[k],fl[k]);
add(to[k],fr[k],fl[k]);
}
}
bool vis[860];
void dfs2(short now){
vis[now]=1;
for(int u=first[now];u;u=edge[u].next){
if(edge[u].flow&&!vis[edge[u].to]){
dfs2(edge[u].to);
}
}
}
void cdq_calc(short l,short r){
if(l>=r)return;
rebuild();
ans[++cnt]=maxflow(p[l],p[r]);
memset(vis,0,sizeof vis);
dfs2(p[l]);int t=l-1;
for(short i=l;i<=r;i++){
if(vis[p[i]]){
swap(p[i],p[++t]);
}
}
cdq_calc(l,t),cdq_calc(t+1,r);
}
int main(){
freopen("cuts.in","r",stdin);
freopen("cuts.out","w",stdout);
splay(n),splay(m);
for(short i=1;i<=m;i++){
splay(fr[i]),splay(to[i]),splay(fl[i]);
}
for(short i=1;i<=n;i++){
p[i]=i;
}
cdq_calc(1,n);
sort(ans+1,ans+cnt+1);
cnt=unique(ans+1,ans+cnt+1)-ans-1;
printf("%d\n",cnt);
//cerr<
T2是czh的代码,自己的WA没调出来
#include
#include
#include
#include
#include
#include
#include
#include
#include
//Copyright(c)2016 liuchenrui
#include
#define LL long long
using namespace std;
inline void splay(int &v){
v=0;char c=0;int p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int s[15];
LL dp[13][2][2][10][12][2][10];//当前位数,是否有8,是否有4,上一位,连续几位,已经有没有3位连续的,是否达到上限
LL dfs(int a,int b,int c,int d,int e,int f,int g){
if(a>11){
if(b&&c)return 0;
if(!f)return 0;
return 1;
}
if(dp[a][b][c][d][e][f][g]!=-1)return dp[a][b][c][d][e][f][g];
LL ret=0;int t;
if(g==0){
for(int i=0;i<=9;i++){
if(i==d)t=e+1;else t=1;
ret+=dfs(a+1,(b|(i==8)),(c|(i==4)),i,t,(t>=3)|(f),0);
}
}
else{
for(int i=0;i=3)|(f),0);
}
if(s[a]==d)t=e+1;else t=1;
ret+=dfs(a+1,(b|(s[a]==8)),(c|(s[a]==4)),s[a],t,(t>=3)|(f),1);
}
return dp[a][b][c][d][e][f][g]=ret;
}
LL calc(LL a){
if(a<10000000000LL)return 0;
for(int i=11;i>=1;i--){
s[i]=a%10;a/=10;
}
memset(dp,-1,sizeof dp);
LL ret=0;
for(int i=1;i>x>>y;
LL a=calc(x-1);
LL b=calc(y);
cout<