18届科大讯飞杯
太懒了,一直放着没怎么补
待
思维构造题
把n=1和n=2的时候特判掉
其他情况下都可以输出n-1种
00
010
0110
01110
…
#include
using namespace std;
signed main(){
int n;cin>>n;
if(n==1)puts("1\n1\n");
else if(n==2)puts("2\n1\n00\n");
else{
cout<<n-1<<endl;
for(int i=2;i<=n;i++){
string ans="0";
for(int j=2;j<=i-1;j++){
ans+='1';
}
ans+='0';
cout<<ans<<endl;
}
}
return 0;
}
满足单调性,因此可以二分
二分天数,用最大流check
源点连接一周的7天,边权为(mid/7)*e,取余多出来的也要加进去
每天连接这一天所能做的事件,边权为inf
每个事件连接汇点,边权为该事件需要完成的数量
如果最大流等于所有事件需要完成的数量总和,则满足,否则不满足
#include
using namespace std;
#define int long long
const int maxm=1e4+5;
vector<int>g[10];
int head[maxm],nt[maxm<<1],to[maxm<<1],w[maxm<<1],cnt;
int c[maxm],sum;
int d[maxm];
int n,e;
void init(){
memset(head,0,sizeof head);
cnt=1;
}
void add(int x,int y,int z){
cnt++;nt[cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
}
bool bfs(int st,int ed){
memset(d,0,sizeof d);
d[st]=1;
queue<int>q;
q.push(st);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=nt[i]){
int v=to[i];
if(w[i]&&!d[v]){
d[v]=d[x]+1;
q.push(v);
if(v==ed)return 1;
}
}
}
return 0;
}
int dfs(int x,int ed,int flow){
if(x==ed)return flow;
int res=flow;
for(int i=head[x];i;i=nt[i]){
int v=to[i];
if(w[i]&&d[v]==d[x]+1){
int k=dfs(v,ed,min(res,w[i]));
w[i]-=k;
w[i^1]+=k;
res-=k;
if(!k)d[v]=-1;
if(!res)break;
}
}
return flow-res;
}
int dinic(int st,int ed){
int ans=0;
while(bfs(st,ed))ans+=dfs(st,ed,1e18);
return ans;
}
int cc[maxm];
int day[10];
bool check(int mid){
init();
int tot=0;
int st=++tot,ed=++tot;//源汇点
for(int i=1;i<=n;i++)cc[i]=++tot;//事件点
for(int i=1;i<=7;i++)day[i]=++tot;//周1到周7的点
for(int i=1;i<=n;i++){//事件->汇点,边权为c[i]
add(cc[i],ed,c[i]);
add(ed,cc[i],0);
}
for(int i=1;i<=7;i++){
int t=(mid/7+(mid%7>=i))*e;
add(st,day[i],t);
add(day[i],st,0);
}
for(int i=1;i<=7;i++){
for(int v:g[i]){
add(day[i],cc[v],1e18);
add(cc[v],day[i],0);
}
}
int ans=dinic(st,ed);
return ans==sum;
}
signed main(){
cin>>n>>e;
for(int i=1;i<=n;i++){
cin>>c[i];
sum+=c[i];//sum记录总次数
int k;cin>>k;
while(k--){
int x;cin>>x;
g[x].push_back(i);
}
}
int l=1,r=1e9;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
return 0;
}