其實這是一道很套路的題目。
首先,我們知道最後的答案之和每行每列的和的最大值有關。
那麼我們可以考慮二分這個最大值然後在判斷可行解。
我們現在已經知道了最大值,那麼要分配方案的話,那麼很明顯就是上下界網路流了。
源點對每行連h[i]-mid為下界,h[i]+mid為上界。
每行向每列連上下界為[l,r]的邊
每列向匯點連上下界為[l[i]-mid,l[i]+mid]的邊
然後判斷是否有可行流就好了:ss連出去的邊是否滿流
然後就沒了。
可能會超時
但是有些人打的不好會超時,那麼該怎麼辦。
首先其實二分的時候可以不用網路流來搞,可以二分的時候把每行每列的範圍加起來,然後判斷行和列的範圍時候有交集,如果有交集那麼就說明可行。
還有乙個優化,就是用zkw來跑,這樣可以跑得超快。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=3e5+7,inf=0x7fffffff;
int i,j,k,l,t,n,m,ans,s,t,x,ss,tt,l,r,r,mid,o,yi,er,yy,ee;
int first[maxn],last[maxn],next[maxn],chang[maxn],fan[maxn],num;
int d[1000],data[maxn],hang[maxn],lie[maxn],an[207][207];
void add(int
x,int
y,int z)
void link(int
x,int
y,int r,int l)
int dinic(int
x,int
y) }
}if(!k)d[x]=-1;
return k;
}bool bfs()}}
return d[tt];
}int main()
yi+=max(l*m,hang[i]-mid),er+=min(r*m,hang[i]+mid);
}fo(i,1,m)
yy+=max(l*n,lie[i]-mid),ee+=min(r*n,lie[i]+mid);
}if(erer||yy>ee)l=mid+1;else r=mid;
}printf("%d\n",l);
memset(first,0,sizeof(first));num=0;
fo(i,1,n)link(s,i,hang[i]+l,max(0,hang[i]-l));
fo(j,1,m)link(n+j,t,lie[j]+l,max(0,lie[j]-l));
fo(i,1,n)fo(j,1,m)link(i,j+n,r,l);
add(t,s,inf);
ans=0;while(bfs())ans+=dinic(ss,inf);
fo(i,1,n)
}fo(i,1,n)
}
GDKOI模擬2016 01 24總結
這場比賽爆零了。原因有很多。現就巨集觀而言,進入初三以後,我在資訊學方面遇到很大的瓶頸和壓力,加之初三學習的重負,oi方面一直有些萎靡不振。儘管退出了培優班,但是我發現由於沒有足夠完善的時間安排,我還是不能保證每天都去機房,很多題都沒時間改,更別提去做其它題目了。學習效率也不是很高,當然這些會形成惡...
GDKOI前模擬總結
連續做了4天的模擬賽,比賽之前打擊一下自信心是很好的事情。一開始看題發現第一題都不會感覺生活沒有希望。然後看第二題,好像做過很多遍了。第三題看了題面都覺得不可做,接著第四題,一直在化簡式子,沒有找到突破點。然後先打了第二題。接著第一題想錯了,以為匹配是對的,對拍的時候發現錯了。然後一直調後來發現整個...
GDKOI2014模擬 樹的直徑
並不想講。樹的直徑有乙個性質。現在有兩棵樹,如果把它們隨意連一條邊,會變成一棵樹,新樹的直徑的端點一定是之前兩棵樹的直徑的共4個端點的兩個。code include include define fo i,x,y for int i x i y i define fd i,x,y for int i...