<ruby id="xh9j9"></ruby>

<th id="xh9j9"></th>

    1. <rp id="xh9j9"><object id="xh9j9"></object></rp>
      <rp id="xh9j9"></rp>

        首頁 > 編程學習 > A層省選4

        A層省選4

        發布時間:8/15/2022 8:34:12 PM

        場均一題放棄

        A. 我

        我切題了

        發現圖上有環可以不停的轉,讓空位到我們需要的地方去,而環的具體形態并不重要,我們只需要知道環的大小(\(size\))和環內元素個數(\(cnt\))即可

        所以使用\(tarjan\)縮點,然后轉化為一個\(DAG\)上的問題

        發現環的大小等于元素個數時,我們必須先移走一個元素,然后可以加入新的元素,但原來的那個元素不能留下

        \(DAG\)轉移中,我們不清楚在有多條可選擇的路徑中應該選擇哪一條

        考慮使用網絡流,拆點

        入點連匯點邊權為\(size\)

        入點連出點\(inf\),出點連\(DAG\)上后繼點的入點

        \(size == cnt\)時源點向入點連\(cnt - 1\),向出點連\(1\),其他情況直接連入點

        這樣存在最后一個小問題,當\(size == cnt == 1\)時,如果該點沒有出度,那么這個孤點沒有移動的理由,不應該扔掉

        所以在建圖前特判即可

        code
        #include <cstring>
        #include <cstdio>
        #include <algorithm>
        #include <cmath>
        #include <iostream>
        #include <queue>
        #include <set>
        #include <vector>
        using namespace std;
        typedef long long ll;
        typedef unsigned long long ull;
        const int maxn = 5005;
        const int mx = 62;
        const int inf = 2147383647;
        char c[maxn];
        int m, flag[maxn];
        int id(char x){
        	if(x >= '0' && x <= '9') return x - '0' + 1;
        	if(x >= 'a' && x <= 'z') return x - 'a' + 10 + 1;
        	return x - 'A' + 10 + 26 + 1;
        }
        vector<int> g[maxn];
        int size[maxn], cnt[maxn], sd[maxn], dt;
        struct wll
        {
        	int head[maxn], tot = 1;
        	struct edge{
        		int net, to, val;
        	} e[maxn << 1 | 1];
        	void add(int u, int v, int w){
        		e[++tot].net = head[u];
        		e[tot].val = w;
        		head[u] = tot;
        		e[tot].to = v;
        	}
        	void link(int u, int v, int w){
        		add(u, v, w);
        		add(v, u, 0);
        	}
        	int s, t;
        	int now[maxn], dep[maxn];
        	bool bfs(){
        		queue<int> q;
        		memset(dep, 0, sizeof(dep));
        		dep[s] = 1;
        		now[s] = head[s];
        		q.push(s);
        		while (!q.empty()){
        			int x = q.front();
        			q.pop();
        			if(x == t) return true;
        			for(int i = head[x]; i; i = e[i].net){
        				int v = e[i].to;
        				if(!dep[v] && e[i].val > 0){
        					now[v] = head[v];
        					dep[v] = dep[x] + 1;
        					q.push(v);
        				}
        			}
        		}
        		return false;
        	}
        	int dfs(int x, int from){
        		if(x == t || from <= 0)return from;
        		int res = from, i;
        		for(i = now[x]; i; i = e[i].net){
        			int v = e[i].to;
        			if(e[i].val > 0 && dep[v] == dep[x] + 1){
        				int k = dfs(v, min(res, e[i].val));
        				if(k <= 0) dep[v] = 0;
        				res -= k;
        				e[i].val -= k;
        				e[i ^ 1].val += k;
        				if(res <= 0) break;
        			}
        		}
        		now[x] = i;
        		return from - res;
        	}
        	int work(){
        		int ans = 0;
        		while (bfs()) ans += dfs(s, inf);
        		return ans;
        	}
        	int cd[maxn];
        	int init(){
        		for(int i = 1; i <= dt + dt + dt; ++i)head[i] = 0;
        		int ans = 0;
        		tot = 1;
        		for(int i = 1; i <= dt; ++i)cd[i] = 0;
        		s = dt + dt + 1, t = s + 1;
        		for(int i = 1; i <= mx; ++i)for(int v : g[i])if(sd[i] != sd[v])link(sd[i] + dt, sd[v], inf), ++cd[sd[i]];
        		for(int i = 1; i <= dt; ++i)if(cd[i] == 0 && cnt[i] == 1)ans += cnt[i], cnt[i] = 0, --size[i];
        		for(int i = 1; i <= dt; ++i)link(i, t, size[i]);
        		for(int i = 1; i <= dt; ++i)link(i, i + dt, inf);
        		for(int i = 1; i <= dt; ++i){
        			if(size[i] > cnt[i])link(s, i, cnt[i]);
        			else link(s, i, cnt[i] - 1), link(s, i + dt, 1);
        		}
        		return work() + ans;
        	}
        }w;
        int dfn[maxn], low[maxn], tim, sta[maxn], top;
        bool vis[maxn];
        void tarjan(int x){
        	low[x] = dfn[x] = ++tim;
        	sta[++top] = x; vis[x] = 1;
        	for(int v : g[x])
        		if(!dfn[v]) tarjan(v), low[x] = min(low[x], low[v]);
        		else if(vis[v]) low[x] = min(low[x], low[v]);
        	if(dfn[x] == low[x]){
        		int y; ++dt;
        		do{
        			y = sta[top--];
        			cnt[dt] += flag[y];
        			++size[dt];
        			sd[y] = dt;
        			vis[y] = 0;
        		} while (y != x);
        	}
        }
        queue<int> q;
        void work(){
        	for(int i = 1; i <= mx; ++i) dfn[i] = 0;
        	for(int i = 1; i <= mx; ++i) low[i] = 0;
        	for(int i = 1; i <= mx; ++i) size[i] = 0;
        	for(int i = 1; i <= mx; ++i) cnt[i] = 0;
        	for(int i = 1; i <= mx; ++i) sd[i] = 0;
        	tim = 0, top = 0, dt = 0;
        	for(int i = 1; i <= mx; ++i) if(!dfn[i]) tarjan(i);
        	printf("%d\n",w.init());
        }
        int main()
        {
        	freopen("graph.in", "r", stdin);
        	freopen("graph.out","w",stdout);
        	int t; scanf("%d", &t);
        	for(int i = 1; i <= t; ++i){
        		for(int i = 0; i <= mx; ++i) flag[i] = 0;
        		for(int i = 0; i <= mx; ++i) g[i].clear();
        		scanf("%s", c + 1);
        		int len = strlen(c + 1);
        		for(int i = 1; i <= len; ++i)flag[id(c[i])] = 1;
        		scanf("%d", &m);
        		for(int i = 1; i <= m; ++i)scanf("%s", c), g[id(c[0])].push_back(id(c[1]));
        		work();
        	}
        	return 0;
        }
        

        B. 想不出

        平面歐拉定理

        可以想象翻轉了坐標軸,向左或者下射線,存在一條折線,其左上都向下,右下都向左

        然后,不會了,看上屆學長的題解,作法是看左側交點多還是下方交點多來定向,不是很理解很是不理解

        code
        #include<cstring>
        #include<cstdio>
        #include<algorithm>
        #include<cmath>
        #include<iostream>
        #include<queue>
        #include<set>
        #include<vector>
        
        using namespace std;
        
        typedef long long ll;
        typedef unsigned long long ull;
        typedef pair<int, int> pii;
        inline int max(int x, int y){return x > y ? x : y;}
        inline int min(int x, int y){return x < y ? x : y;}
        inline void swap(int &x, int &y){x ^= y, y ^= x, x ^= y;}
        const int maxn = 2005;
        const int inf = 2147383647;
        int n;
        struct node{
        	int x,y;
        	double k1, b1, k2, b2;
        	bool operator < (const node &b)const{return x == b.x ? y < b.y : x < b.x;}
        }d[maxn];
        int dir[maxn], vis[maxn];
        bool check(int x, int y){
        	double a = (d[y].b1 - d[x].b2) / (d[x].k2 - d[y].k1);
        	return d[x].x <= a && a <= d[y].x;
        }
        int main(){
        	freopen("surface.in","r",stdin);
        	freopen("surface.out","w",stdout);
        	scanf("%d",&n);
        	for(int i = 1; i <= n; ++i)scanf("%d%d",&d[i].x, &d[i].y);
        	sort(d + 1, d + n + 1);
        	for(int i = 1; i <= n; ++i){
        		d[i].k1 = (double) sqrt(3);
        		d[i].k2 = -d[i].k1;
        		d[i].b1 = d[i].y - d[i].k1 * d[i].x;
        		d[i].b2 = d[i].y - d[i].k2 * d[i].x;
        	}
        	for(int i = 1; i <= n; ++i){
        		int c1 = 0, c2 = 0;
        		for(int j = 1; j < i; ++j)if(check(j, i))++c1;
        		for(int j = n; j > i; --j)if(check(i, j))++c2;
        		dir[i] = c1 < c2 ? 1 : 0;
        	}
        	int ans = 0;
        	for(int i = 1; i <= n; ++i)
        		if(dir[i]){
        			int now = -1;
        			for(int j = i + 1; j <= n; ++j)if(!dir[j])
        				if(check(i, j)){if(!vis[j])vis[j] = 1; else ++now;}
        			ans += max(now, 0);
        		}
        	printf("%d\n",ans);
        	return 0;
        }
        

        C. 題目名稱

        不要被數據范圍嚇到,背包有\(45pts\)

        正解不會
        image

        45
        #include<cstring>
        #include<cstdio>
        #include<algorithm>
        #include<cmath>
        #include<iostream>
        #include<queue>
        #include<set>
        #include<vector>
        
        using namespace std;
        
        typedef long long ll;
        typedef unsigned long long ull;
        typedef pair<int, int> pii;
        inline int max(int x, int y){return x > y ? x : y;}
        inline int min(int x, int y){return x < y ? x : y;}
        inline void swap(int &x, int &y){x ^= y, y ^= x, x ^= y;}
        inline ll read(){
        	ll x = 0; char c = getchar();
        	while(c < '0' || c > '9')c = getchar();
        	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
        	return x;
        }
        const int maxn = 1000005;
        const int inf = 2147383647;
        const int mod = 998244353;
        ll n, s;
        ll f[5][maxn];
        int vis[maxn];
        void work(int l, int r){
        	for(int i = l; i <= r; ++i){
        		if(vis[i]){i = vis[i];continue;} vis[i] = r;
        		for(int k = 3; k >= 0; --k)
        			for(int j = 0; j <= s - i; ++j)
        		 		f[k + 1][j + i] = (f[k + 1][j + i] + f[k][j]) % mod;
        	}
        }
        int main(){
        	freopen("count.in","r",stdin);
        	freopen("count.out","w",stdout);
        	n = read(), s = read();
        	f[0][0] = 1;
        	for(int i = 1; i <= n; ++i){
        		int l = read(), r = read();
        		work(l, r);
        	}
        	printf("%lld\n",f[4][s]);
        	return 0;
        }
        
        
        Copyright ? 2010-2022 wtld.cn 版權所有 |關于我們| 聯系方式
        日本精品人妻

        <ruby id="xh9j9"></ruby>

        <th id="xh9j9"></th>

        1. <rp id="xh9j9"><object id="xh9j9"></object></rp>
          <rp id="xh9j9"></rp>