当不满足要求的数超过4个的时候,肯定是无解的,否则用每个数和这4个数交换,然后check。。比赛的时候写了很繁琐的分类讨论,竟然没挂。。
#include <bits/stdc++.h>
#include <unordered_map>
#define ll long long
using namespace std;
int a[150010];
int err[150010];
int n;
bool judge(){
for(int i=1;i<n;i++){
if(i&1){
if(a[i]>=a[i+1]){
return 0;
}
}else{
if(a[i]<=a[i+1]){
return 0;
}
}
}
return 1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int cnt= 0;
for(int i=1;i<n;i++){
if(i&1){
if(a[i]>=a[i+1]){
err[cnt++] = i;
}
}else{
if(a[i]<=a[i+1]){
err[cnt++] = i;
}
}
}
int ans = 0;
if(cnt>4){
}else if(cnt==4){
if(err[0]+1==err[1] && err[2]+1==err[3]){
swap(a[err[1]],a[err[3]]);
ans+=judge();
swap(a[err[1]],a[err[3]]);
}else{
}
}else if(cnt==3){
if(err[0]+2==err[2]){
swap(a[err[1]],a[err[2]]);
ans+=judge();
swap(a[err[1]],a[err[2]]);
swap(a[err[1]],a[err[2]+1]);
ans+=judge();
swap(a[err[1]],a[err[2]+1]);
swap(a[err[0]],a[err[2]]);
ans+=judge();
swap(a[err[0]],a[err[2]]);
}if(err[0]+1==err[1]){
swap(a[err[1]],a[err[2]]);
ans+=judge();
swap(a[err[1]],a[err[2]]);
swap(a[err[1]],a[err[2]+1]);
ans+=judge();
swap(a[err[1]],a[err[2]+1]);
}else if(err[1]+1==err[2]){
swap(a[err[0]],a[err[2]]);
ans+=judge();
swap(a[err[0]],a[err[2]]);
swap(a[err[0]+1],a[err[2]]);
ans+=judge();
swap(a[err[0]+1],a[err[2]]);
}else{
}
}else if(cnt==2){
if(err[0]+1==err[1]){
swap(a[err[0]],a[err[1]+1]);
ans+=judge();
swap(a[err[0]],a[err[1]+1]);
for(int i=1;i<=n;i++){
swap(a[i],a[err[1]]);
bool ok = 1;
for(int j=i-3;j<=i+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
for(int j=err[1]-3;j<=err[1]+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
swap(a[i],a[err[1]]);
ans+=ok;
}
}else{
swap(a[err[0]],a[err[1]]);
ans+=judge();
swap(a[err[0]],a[err[1]]);
swap(a[err[0]],a[err[1]+1]);
ans+=judge();
swap(a[err[0]],a[err[1]+1]);
swap(a[err[0]+1],a[err[1]]);
ans+=judge();
swap(a[err[0]+1],a[err[1]]);
swap(a[err[0]+1],a[err[1]+1]);
ans+=judge();
swap(a[err[0]+1],a[err[1]+1]);
}
}else if(cnt==1){
for(int i=1;i<=n;i++){
swap(a[i],a[err[0]]);
bool ok = 1;
for(int j=i-3;j<=i+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
for(int j=err[0]-3;j<=err[0]+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
swap(a[i],a[err[0]]);
ans+=ok;
}
for(int i=1;i<=n;i++){
if(i==err[0])continue;
swap(a[i],a[err[0]+1]);
bool ok = 1;
for(int j=i-3;j<=i+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
for(int j=err[0]-3;j<=err[0]+3;j++){
if(j<1)continue;
if(j>=n)continue;
if(j&1){
if(a[j]>=a[j+1]){
ok = 0;
}
}else{
if(a[j]<=a[j+1]){
ok = 0;
}
}
}
swap(a[i],a[err[0]+1]);
ans+=ok;
}
}
cout<<ans<<endl;
return 0;
}
这是一道好题!解法是二分答案,然后跑最大流判是否可行。判断方法是将边的流量改为它除以答案的值,向下取整,如果最大流不小于x就是合法。
另外要注意,二分写成循环固定次数会比较好。
#include <bits/stdc++.h>
#include <unordered_map>
#define ll long long
using namespace std;
int n,m;
double x;
const int inf=0xfffff;
const int N = 55;
int pre[N];
double maxflow,dp[N][N];
double tmp[N][N];
void Edmonds_Karp(int start, int end, int m){
while(1){
queue<int> p;
double minflow = inf;
p.push(1);
memset(pre, 0, sizeof(pre));
while(!p.empty()){
int u = p.front();
p.pop();
if(u == end)
break;
for(int i = 1;i <= m;i++)
if(dp[u][i] > 0&&pre[i] == 0){
pre[i] = u;
p.push(i);
}
}
if(pre[end] == 0)
break;
for(int i = end;i != start;i = pre[i])
minflow = min(minflow, dp[pre[i]][i]);
for(int i = end;i != start;i = pre[i]) {
dp[pre[i]][i] -= minflow;
dp[i][pre[i]] += minflow;
}
maxflow+=minflow;
}
}
int main(){
cin>>n>>m>>x;
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
dp[a][b]+=c;
}
memcpy(tmp,dp,sizeof(dp));
double l=0;
double r=1000000;
double mid = 0;
//注意这个二分的姿势
for(int tt=0;tt<66;tt++){
mid = (l+r)/2;
memcpy(dp,tmp,sizeof(dp));
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
dp[i][j] = floor(dp[i][j]/mid);
}
}
maxflow = 0;
Edmonds_Karp(1,n,n);
if(maxflow>=x){
l=mid;
}else{
r=mid;
}
}
printf("%.10f\n",mid*x);
return 0;
}