上机考试资料

最长不下降子序列

正一遍反一遍求子序列就行。

#include <bits/stdc++.h>
using namespace std;
#define N 101
#define ll long long

template <class T>
inline T read(T& a){
    T x = 0, s = 1;
    char c = getchar(); 
    while(!isdigit(c)){ if(c == '-')  s = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return a; 
}

int n; 
int a[N];
int b[N]; 
int dp1[N], dp2[N]; 

int main(){
    //freopen("hh.txt", "r", stdin); 
    cin >> n; 
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    for(int i = 1; i <= n; i++)
        b[i] = a[n - i + 1]; 
    int ans = 1e9; 
    for(int top = 0; top <= n + 1; top++){
        memset(dp1, 0, sizeof(dp1)); 
        memset(dp2, 0, sizeof(dp2)); 
        int maxn1 = 0, maxn2 = 0; 
        for(int i = 1; i <= top; i++){
            dp1[i] = 1; 
            dp2[i] = 1; 
            for(int j = 1; j < i; j++){
                if(a[i] > a[j]) dp1[i] = max(dp1[i], dp1[j] + 1); 
            }
        }
        for(int i = 1; i <= n - top + 1; i++){
            dp2[i] = 1; 
            for(int j = 1; j < i; j++)
                if(b[i] > b[j]) dp2[i] = max(dp2[i], dp2[j] + 1); 
        }
        ans = min(ans, n - dp1[top] - dp2[n - top + 1] + 1); 
    }
    cout << ans << endl; 
    return 0; 
}

最小生成树

#include <bits/stdc++.h>
using namespace std;
#define N 101
#define ll long long

template <class T>
inline T read(T& a){
    T x = 0, s = 1;
    char c = getchar(); 
    while(!isdigit(c)){ if(c == '-')  s = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return a; 
}

int n; 
int dis[N][N]; 

struct node{
    int u, v, w; 

    bool operator < (const node &a) const{
        return w < a.w; 
    }
} t[N * N]; 

int fa[N]; 
int find_fa(int x){
    return x == fa[x] ? x : fa[x] = find_fa(fa[x]); 
}

bool issame(int u, int v){
    return find_fa(u) == find_fa(v); 
}

void merge(int u, int v){
    int fau = find_fa(u), fav = find_fa(v); 
    if(fau != fav) fa[fau] = fav;
    return ; 
}

int cnt = 0; 
int kruskal(){
    int sum = 0; 
    sort(t + 1, t + cnt + 1); 
    for(int i = 1; i <= cnt; i++){
        int u = t[i].u, v = t[i].v; 
        if(!issame(u, v)){
            merge(u, v); 
            sum += t[i].w; 
        }
    }
    return sum; 
}

int main(){
    //freopen("hh.txt", "r", stdin); 
    read(n); 
    
    for(int i = 1; i <= n; i++)
        fa[i] = i; 
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            read(dis[i][j]); 
            t[++cnt] = (node){i, j, dis[i][j]}; 
        }
    }
    cout << kruskal() << endl; 
    return 0; 
}

二分图最大匹配(旬牙利算法)

#include <bits/stdc++.h>
using namespace std;
#define N 700010

inline int read(){
	int x = 0,s = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-')s = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9'){
		x = (x << 1) + (x << 3) + (c ^ '0');
		c = getchar();
	}
	return x * s;
}

int n,m,e;
int f[N];
struct node{
	int u,v,next;
} t[N];
int ti = 1,ans = 0;
int match[N];
int dfn[N];
bool vis[N];

int cnt = 0;
void add(int u,int v){
	cnt++;
	t[cnt].v = v;
	t[cnt].u = u;
	t[cnt].next = f[u];
	f[u] = cnt;
	return;
}

bool dfs(int now,int ti){
	for(int i = f[now]; i;i = t[i].next){
		int v = t[i].v;
		if(dfn[v] != ti){
			dfn[v] = ti;	
			if(!match[v] || dfs(match[v],ti)){
				match[v] = t[i].u;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
//	freopen("hh.txt","r",stdin);
	n = read(),m = read(),e = read();
	for(int i = 1;i <= e; i++){
		int u = read(),v = read();
		if(u > n || v > m)continue;
		add(u,v);
	}
	for(int i = 1;i <= n; i++)
		if(dfs(i,++ti))ans++; 
	printf("%d",ans);
	return 0;
}

网络最大流 (Dicnic)

#include<bits/stdc++.h>
using namespace std;
#define N 500010 
#define ll long long
const ll INF = ~0u >> 1;

inline ll read(){
	ll x = 0,s = 1;
	char c = getchar();
	while(!isdigit(c)){
		if(c == '-')s = -1;
		c=  getchar();
	}
	while(isdigit(c)){
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * s;
}

struct node{
	ll u,v,next = -1,w;
} t[N];

ll n,m,s,ht;
ll f[N],cur[N];
ll deth[N];

ll cnt = -1;
void add(ll u,ll v,ll w){
	cnt++;
	t[cnt].u = u;
	t[cnt].v = v;
	t[cnt].w = w;
	t[cnt].next = f[u];
	f[u] = cnt;

	return;
}

bool vis[N];
queue <ll> q;
void clean2(){
	memset(deth,0,sizeof(deth));
	while(!q.empty())q.pop();
	return;
}

bool bfs(){
	clean2();
	q.push(s);
	deth[s] = 1;
	while(!q.empty()){
		ll now = q.front();
		q.pop();
		for(ll i = f[now];i != -1; i = t[i].next) {
			ll v = t[i].v,w = t[i].w,u = t[i].u;
			if(!deth[v] && w != 0){
				deth[v] = deth[u] + 1;
				q.push(v); 
			}
		}
	}
	if(deth[ht])
		return 1;
	else return 0;	
} 

ll dfs(ll now,ll dist){
	if(now == ht)return dist;
	for(ll& i = cur[now];i != -1; i = t[i].next){
		cur[now] = i; // 当前弧优化
		ll v = t[i].v;
		if(deth[v] == deth[now] + 1 && t[i].w != 0){
			ll di = dfs(v, min(dist, t[i].w));
			if(di > 0){
				t[i].w -= di;
				t[i^1].w += di;
				return di;
			}
		}
	}	
	return 0; 
}

ll answer(){
	ll ans = 0;
	while(bfs()){
		memcpy( cur, f, sizeof(cur) );
		while(ll temp = dfs(s,INF))
			ans += temp;
	}
	return ans;
}

void clean(){
	cnt = -1;
	memset(f,-1,sizeof(f));
	return;
}

int main(){
	//freopen("hh.txt","r",stdin);
	n = read(),m = read(),s = read(),ht = read();
	clean();
	for(ll i = 0;i < m; i++){
		ll x = read(),y = read(),z = read();
		add(x,y,z);
		add(y,x,0);//加虚边 
	}
	printf("%lld",answer());
	return 0;
}

差分约束

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long

template <class T>
inline void read(T& a){
    T x = 0, s = 1;
    char c = getchar(); 
    while(!isdigit(c)){ if(c == '-')  s = -1; c = getchar(); }
    while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
    a = x * s;
    return ; 
}

struct node{
    int u, v, w, next; 
} t[N]; 
int head[N]; 

int bian = 0; 
inline void addedge(int u, int v, int w){
    t[++bian] = (node){u, v, w, head[u]}, head[u] = bian; 
    // t[++bian] = (node){v, u, w, head[v]}, head[v] = bian; 
    return ; 
}

int n, m; 
int in[N]; 

int cac[N]; 
ll dis[N]; 
bool vis[N]; 

int spfa(int s){
    queue <int> q; 
    q.push(s); 
    for(int i = 0; i <= n; i++){
        dis[i] = 1e9; 
    }
    dis[s] = 0; 
    while(!q.empty()){
        int u = q.front(); q.pop(); 
        vis[u] = 0; 
        // cac[u]++; 
        // if(cac[u] == n) return -1; 
        for(int i = head[u]; i; i = t[i].next){
            int v = t[i].v; 
            if(dis[v] >= dis[u] + t[i].w){
                dis[v] = dis[u] + t[i].w; 
                if(!vis[v]) q.push(v), vis[v] = 1; 
            }
        }
    }
    return 1; 
}

int main(){
    //freopen("hh.txt", "r", stdin); 
    read(n), read(m); 
    for(int i = 1; i <= m; i++){
        int x, y, w; 
        read(x), read(y), read(w); 
        addedge(y, x, w);   // x - y <= w -> x <= y + w -> y连x求最短路。最长路情况同理。二者可以加负号转换
    }
    for(int i = 1; i <= n; i++){
        addedge(0, i, 0); 
    }
    spfa(0); 
    for(int i = 1; i <= n; i++)
        cout << dis[i] << " "; 
    return 0; 
}

posted @ 2024-06-25 16:08  雪之下,树之旁  阅读(10)  评论(0编辑  收藏  举报