源符「厌川的翡翠」
题目更新:
现在第13,14,15,16组数据满足m=n-1
所有整数都是正整数
第7,8,9,10,11,12组数据的范围更改为:n,t<=40, m<=50
已添加一句话题意
已将样例2更换为更强的样例
请不要在代码或评论中添加任何可能引起时间以秒为单位变化的内容
【题目描述】
诹访子和神奈子需要合力帮助早苗!
早苗作为神社的风祝,有时也需要解决异变,但在一次异变中早苗遇到了非常强大的敌人,需要诹访子和神奈子的援助。诹访子打算使用符卡”源符「厌川的翡翠」”来帮助早苗,同时神奈子会使用藤蔓来增加诹访子符卡的威力。
符卡”源符「厌川的翡翠」”会放出n个翡翠,神奈子则会操纵m条藤蔓连接这些翡翠,一些翡翠可能会被藤蔓连接成一个环,但是没有两个翡翠连成的环中有相同的藤蔓,所有的翡翠都能通过藤蔓连接到其它翡翠。在战斗中诹访子可以任意将翡翠的硬度调节为[1,t]中的整数,如果第i个翡翠的硬度为j,则整个符卡会获得v[i][j]的不稳定系数,而且符卡的威力和用藤蔓连接的两个翡翠硬度的差值有关。
由于诹访子并不擅长数学,早苗又要与敌人交战,所以她请你来帮她找到一个最小的整数c,满足存在一种给翡翠设置硬度的方案,使得没有两个被藤蔓连接的翡翠硬度的差值大于c且所有翡翠的不稳定系数之和不大于w。
一句话题意:
给个仙人掌,仙人掌上每个点都能填入[1,t]中的整数,第i个点填j会获得收益v[i][j],求一个最小的c,使得存在一种填数的方案,满足没有两个用边相邻的点填的数差值超过c且所有点的收益和不超过w
【输入格式】
第一行四个整数n,m,w,t,意义如上
接下来m行,每行三个整数l和r,表示第l个铁轮和第r个翡翠用藤蔓连接在一起
接下来一个n行t列的整数矩阵,第i行第j列的数表示第i个翡翠硬度为j所获得的不稳定系数
【输出格式】
如果敌人太强了诹访子和神奈子联手都无法战胜,输出-1
否则一行一个整数c,意义如上
【样例输入1】
5 5 5 2
1 2
1 4
3 4
4 5
3 5
1 2
2 1
1 2
2 1
1 2
【样例输出1】
1
【样例输入2】
10 11 20 10
1 2
1 3
3 4
2 5
3 6
6 7
3 8
1 9
1 10
1 8
1 5
7 2 3 9 9 10 10 4 4 7
1 7 1 9 3 1 1 2 4 6
1 2 10 3 5 10 3 5 5 4
1 9 3 8 4 4 2 2 3 2
2 4 1 10 7 7 8 3 8 7
9 3 8 3 2 10 7 3 10 1
3 3 7 7 4 9 3 7 10 5
9 5 8 7 1 3 2 10 5 8
9 10 10 10 4 6 2 9 4 9
7 10 8 10 2 1 4 3 9 10
【样例输出2】
3
【数据范围】
n,t<=150,m<=200,w<=100000,v<=5000000
【ex】
还有诹访子和神奈子联合起来都打不过的人(妖怪/神……)?
正邪啊,谁自机谁最强
吓得我都去玩 弹幕天邪鬼 了↓↓↓
《论根据名字选择题目的优越性2》
这题就是咱去做切糕的原因……
思路:
可以先去看看切糕
(这是一道题的名字不要误会)
看完想必就不需要往下看了,可以直接做出这道题了……
好吧其实还是有一点点区别的……
咱考虑二分这个答案c,使用网络流判断。
然后判定方法嘛……瞬间变成了切糕是不是呀……
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0' || '9'<ch)ch=getchar();
while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
return x;
}
typedef pair<int,int> pr;
const int NN=159;
const int Inf=1e9;
int n,m,w,d;
vector<pr> wea;
int v[NN][NN];
const int N=1e5+9;
const int M=1e6+9;
inline int po(int u,int d)
{
return u+(d-1)*n;
}
int to[M],nxt[M],cap[M],beg[N],tot;
int s,t,dis[N],q[N];
inline void adde(int u,int v,int c)
{
to[++tot]=v;
nxt[tot]=beg[u];
cap[tot]=c;
beg[u]=tot;
}
inline void add(int u,int v,int c)
{
adde(u,v,c);
adde(v,u,0);
}
inline bool bfs()
{
int l=0,r=1;
memset(dis,0,sizeof(dis));
q[1]=s;
dis[s]=1;
while(l<r)
{
int u=q[++l];
for(int i=beg[u],v;i;i=nxt[i])
if(!dis[v=to[i]] && cap[i])
{
dis[v]=dis[u]+1;
q[++r]=v;
}
}
return dis[t];
}
inline int dfs(int u,int mflow)
{
if(u==t || !mflow)
return mflow;
int cost=0;
for(int i=beg[u],v,f;i;i=nxt[i])
if(dis[v=to[i]]==dis[u]+1 && cap[i])
{
f=dfs(v,min(mflow-cost,cap[i]));
cap[i]-=f;
cap[i^1]+=f;
cost+=f;
if(mflow==cost)
break;
}
if(!cost)
dis[u]=-1;
return cost;
}
inline int dinic()
{
int ret=0;
while(bfs())
ret+=dfs(s,Inf);
return ret;
}
inline void init()
{
memset(nxt,0,sizeof(nxt));
memset(beg,0,sizeof(beg));
tot=1;
}
inline bool judge(int c)
{
init();
for(int j=1;j<=n;j++)
{
add(s,po(j,1),Inf);
add(po(j,d),t,v[j][d]);
for(int i=1;i<d;i++)
add(po(j,i),po(j,i+1),v[j][i]);
}
for(int i=0,e=wea.size();i<e;i++)
for(int j=1+c;j<=d;j++)
{
add(po(wea[i].first,j),po(wea[i].second,j-c),Inf);
add(po(wea[i].second,j),po(wea[i].first,j-c),Inf);
}
return dinic()<=w;
}
int main()
{
freopen("cdcq_c.in","r",stdin);
freopen("cdcq_c.out","w",stdout);
n=read();m=read();
w=read();d=read();
s=n*d+1;t=s+1;
for(int i=1;i<=m;i++)
wea.push_back((pr){read(),read()});
for(int i=1;i<=n;i++)
for(int j=1;j<=d;j++)
v[i][j]=read();
int l=0,r=d+1,mid,ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(judge(mid))
ans=mid,r=mid-1;
else
l=mid+1;
}
printf("%d\n",ans);
return 0;
}