匈牙利算法
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#define mp(x,y) make_pair((x),(y))
using namespace std;
const int N=1e5+5;
struct node{
int y,nt;
}a[N*2];
int n,m,E,head[N],tot,link[N];
bool v[N];
map<pair<int,int>,bool>b;
void add(int x,int y){
a[++tot]=(node){y,head[x]}; head[x]=tot;
}
bool hungry(int x){
for(int i=head[x];i;i=a[i].nt){
int y=a[i].y;
if (!v[y]){
v[y]=1;
int q=link[y];
link[y]=x;
if (!q||hungry(q)) return 1;
link[y]=q;
}
}
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&E);
for(int i=1;i<=E;i++){
int x,y;
scanf("%d%d",&x,&y);
if (!b[mp(x,y)]) add(x,y); else b[mp(x,y)]=1;
}
int ans=0;
for(int i=1;i<=n;i++) {
memset(v,0,sizeof(v));
if (hungry(i)) ans++;
}
printf("%d",ans);
return 0;
}
离散化
sort(Q+1,Q+1+q);
q=unique(Q+1,Q+1+q)-Q-1;
rep(i,1,m){
d[i]=lower_bound(Q+1,Q+q+1,d[i])-Q;
最长公共上升子序列
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+5;
int n,belong[N],b[N],len;
int main(){
scanf("%d",&n);
int x;
for(int i=1;i<=n;i++) scanf("%d",&x),belong[x]=i;
for(int i=1;i<=n;i++){
scanf("%d",&x);
if (belong[x]>b[len]) b[++len]=belong[x];
else b[lower_bound(b+1,b+len+1,belong[x])-b]=belong[x];
}
printf("%d",len);
return 0;
}
单调栈
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int N=3e6+5;
stack<int>sk;
int n,f[N],d[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&f[i]);
for(int i=1;i<=n;i++){
while (sk.size()&&f[sk.top()]<f[i]) d[sk.top()]=i,sk.pop();
sk.push(i);
}
for(int i=1;i<=n;i++) printf("%d ",d[i]);
return 0;
}
博弈
.。。。。。。。
康拓展开
最小表示法
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[600010],ans;
int main()
{
scanf("%d",&n);
for (int w=1;w<=n;w++) scanf("%d",&a[w]),a[w+n]=a[w];
int i=1,j=2,k=0;
while (i<=n&&j<=n)
{
k=0; while (k<=n&&a[i+k]==a[j+k])k++;
if (k==n) break;
if (a[i+k]>a[j+k]) {i=i+k+1; if (i==j) i++;}
else {j=j+k+1; if (i==j) j++;}
}
ans=min(i,j);
for (int w=ans;w<=ans+n-1;w++)
printf("%d ",a[w]);
}
缩点
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+5;
struct node{
int x,y,nt;
}a[N*2];
struct node1{
int y,nt;
}A[N*2];
int cnt,n,m,p[N],low[N],dfn[N],s[N],belong[N];
int tot,head[N],head1[N],tot1;
queue<int>q;
int dis[N],in[N];
void add(int x,int y){
a[++tot]=(node){x,y,head[x]}; head[x]=tot;
}
void add1(int x,int y){
A[++tot1]=(node1){y,head1[x]}; head1[x]=tot1; in[y]++;
}
int num;
bool B[N];
void tarjan(int x){
low[x]=dfn[x]=++cnt;
s[++num]=x; B[x]=1;
for(int i=head[x];i;i=a[i].nt){
int y=a[i].y;
if (!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if (B[y]) low[x]=min(low[x],dfn[y]);
}
if (dfn[x]==low[x]){
int y;
while (y=s[num--]){
belong[y]=x;
B[y]=0;
if (x==y) break;
p[x]+=p[y];
}
}
}
int topo(){
while (q.size()) q.pop();
for(int i=1;i<=n;i++) if (belong[i]==i&&!in[i]) q.push(i),dis[i]=p[i];
while (q.size()){
int x=q.front(); q.pop();
for(int i=head1[x];i;i=A[i].nt){
int y=A[i].y;
dis[y]=max(dis[y],dis[x]+p[y]);
in[y]--;
if (!in[y]) q.push(y);
}
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,dis[i]);
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for(int i=1;i<=tot;i++) if (belong[a[i].x]!=belong[a[i].y]) add1(belong[a[i].x],belong[a[i].y]);
printf("%d",topo());
return 0;
}
割点
void tarjan(int x){
low[x]=dfn[x]=++cnt;
s[++num]=x; B[x]=1;
// int flag=0;
for(int i=head[x];i;i=a[i].nt){
int y=a[i].y;
if (!dfn[y]){
tarjan(y),low[x]=min(low[x],low[y]); /*
if (low[y]>=dfn[x]){
flag++;
if (x!=root&&flag>1) bb[x]=1;
}*/
}
else if (B[y]) low[x]=min(low[x],dfn[y]);
}
}
最大流
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const ll N=2e5+5,inf=1e18;
struct node{
ll y,z,nt;
}a[N];
ll tot=1,head[N],dep[N],cur[N];
ll n,m,s,t;
void add(ll x,ll y,ll z){
a[++tot]=(node){y,z,head[x]}; head[x]=tot;
a[++tot]=(node){x,0,head[y]}; head[y]=tot;
}
queue<ll>q;
bool bfs(){
memset(dep,0,sizeof(dep));
while (q.size()) q.pop();
q.push(s); dep[s]=1;
while (q.size()){
ll x=q.front(); q.pop();
for(ll i=head[x];i;i=a[i].nt){
ll y=a[i].y;
if (a[i].z&&!dep[y]){
dep[y]=dep[x]+1;
if (y==t) return 1;
q.push(y);
}
}
}
return 0;
}
ll dinic(ll x,ll maxf){
if (x==t||!maxf) return maxf;
ll ret=0;
for(ll &i=cur[x];i;i=a[i].nt){
ll y=a[i].y;
if (a[i].z&&dep[y]==dep[x]+1){
ll ff=dinic(y,min(a[i].z,maxf-ret));
a[i].z-=ff;
a[i^1].z+=ff;
ret+=ff;
if (ret==maxf) break;
}
}
return ret;
}
int main(){
scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
for(ll i=1;i<=m;i++){
ll x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
}
ll ans=0;
while (bfs()) {
for(ll i=1;i<=n;i++) cur[i]=head[i];
ans+=dinic(s,inf);
}
printf("%lld",ans);
return 0;
}
最小费用最大流
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
struct node{
int y,coat,z,nt;
}a[N*2];
int tot=1,head[N];
int n,m,s,t;
void add(int x,int y,int coat,int z){
a[++tot]=(node){y,coat,z,head[x]}; head[x]=tot;
a[++tot]=(node){x,-coat,0,head[y]}; head[y]=tot;
}
int maxflow,ans,d[N],pre[N],inc[N];
bool vis[N];
bool spfa(){
queue<int>q;
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
q.push(s); d[s]=0; vis[s]=1; inc[s]=inf;
while(q.size()){
int x=q.front(); q.pop();
for(int i=head[x];i;i=a[i].nt){
int y=a[i].y;
if (a[i].z==0) continue;
if (d[y]>d[x]+a[i].coat){
d[y]=d[x]+a[i].coat;
inc[y]=min(inc[x],a[i].z);
pre[y]=i;
if (!vis[y]) vis[y]=1,q.push(y);
}
}
vis[x]=0;
}
return (d[t]==inf)?0:1;
}
void update(){
int x=t;
while(x!=s){
int i=pre[x]; a[i].z-=inc[t]; a[i^1].z+=inc[t]; x=a[i^1].y;
}
maxflow+=inc[t]; ans+=d[t]*inc[t];
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++){
int x,y,coat,z;
scanf("%d%d%d%d",&x,&y,&z,&coat);
add(x,y,coat,z);
}
while (spfa()) update();
printf("%d %d",maxflow,ans);
return 0;
}