• CCPC-Wannafly Summer Camp 2019 Day1


    A - Jzzhu and Cities

     题目大意:给个图,m条普通边,k条特殊边,保证1到N的最短路上最多可以删掉几条特殊边使得最短路不变。

    解法1:跑最短路后松弛一遍所有边,如果松弛时既有普通和特殊则可去掉特殊铁路。

    解法2:直接重载搜索顺序使得迪杰斯特拉优先跑普通铁路,再记录总特殊条数-跑的条数即为答案。

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef std::pair<int, int> pii;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    const int MAXN = 1e6 + 10;
    
    int n, m, k;
    
    
    bool used[MAXN];
    
    struct node
    {
    	ll to, val, ok;
    	node() { }
    	node(ll a, ll b, ll c) { to = a, val = b, ok = c; }
    };
    
    vector <node> edge[MAXN];
    
    struct bfsnode
    {
    	ll now, dis, cnt;
    	bfsnode() { }
    	bfsnode(ll a, ll b, ll c) { now = a, dis = b, cnt = c; }
    };
    
    bool operator < (bfsnode a, bfsnode b)
    {
    	if(a.dis == b.dis)
    		return a.cnt > b.cnt;
    	return a.dis > b.dis; 
     } 
    
    void bfs()
    {
    	priority_queue <bfsnode> PQ;
    	
    	PQ.push(bfsnode(1, 0, 0));
    	
    	ll ans = 0;
    	
    	while(!PQ.empty())
    	{
    		bfsnode rnow = PQ.top();
    		PQ.pop();
    		
    		if(used[rnow.now])
    			continue;
    			
    		used[rnow.now] = true;
    		
    		if(rnow.cnt)
    			++ans;
    		
    		for(auto x : edge[rnow.now])
    		{
    			PQ.push(bfsnode(x.to, rnow.dis + x.val, x.ok));
    		}
    	}
    	
    	cout << k - ans << '
    ';
    }
     
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        
    	//freopen("azerah.in","r",stdin); 
    	//freopen("azerah.out","w",stdout); 
    	
    	cin >> n >> m >> k;
    	
    	for(int i = 0; i < m; ++i)
    	{
    		ll a, b, c;
    		cin >> a >> b >> c;
    		edge[a].push_back(node(b, c, 0));
    		edge[b].push_back(node(a, c, 0));
    	}
    	
    	for(int i = 0; i < k; ++i)
    	{
    		ll a, b;
    		cin >> a >> b;
    		edge[1].push_back(node(a, b, 1));
    		edge[a].push_back(node(1, b, 1));
    	}
    	
    	bfs();	
       	
     
        return 0;
    }
    

    B - Phillip and Trains

    人只能向右一步同时向上 或 向下 或不动, 然后火车向左两步,求会不会被撞。

    解法:相对运动转化+二维dp,当前位置只能由三个位置转移而来,如果能转移到最右端则不会被撞

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef std::pair<int, int> pii;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    const int MAXN = 4e6 + 10;
    
    char arr[5][200];
    int ok[5][200];
    
    bool check(int x, int y)
    {
    	if ( arr[x][y] != '.' || arr[x][y - 1] != '.' || arr[x][y - 2] != '.')
    		return false;
    		
    	if(arr[x][y - 3] == '.' && ok[x][y - 3])
    		return true;
    	
    	if(x != 2)
    	{
    		if(arr[x + 1][y - 2] == '.' && arr[x + 1][y - 3] == '.' && ok[x + 1][y - 3])
    			return true;
    	}
    	if(x != 0)
    	{
    		if(arr[x - 1][y - 2] == '.' && arr[x - 1][y - 3] == '.' && ok[x - 1][y - 3])
    			return true;
    	}
    	return false;
    }
    int main()  
    {   
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);  
        
        int t;
        
        cin >> t;
        
        while(t--)
        {
        	memset(arr, '.', sizeof(arr));
        	memset(ok, 0, sizeof(ok));
        	
        	int n, k;
        	
        	cin >> n >> k;
        	
        	for(int i = 0; i < 3; ++i)
        	{
        		for(int j = 0; j < n; ++j)
        		{
        			cin >> arr[i][j];
        			if(arr[i][j] == 's')
        				ok[i][j] = 1, arr[i][j] = '.';
    			}
    		}
    		
    		bool flag = false;
    		
    		for(int j = 3; j < n + 10; j++)
    		{
    			for(int i = 0; i < 3; ++i)
    			{
    				if(check(i, j))
    				{
    					ok[i][j] = true;
    					if(j >= n - 1)
    						flag = true;
    				}
    			}
    		}
    		
    //		for(int i = 0; i < 3; ++i)
    //		{
    //			for(int j = 0; j < n; ++j)
    //			{
    //				cout << ok[i][j] ;
    //			}
    //			cout << '
    ';
    //		}
    		
    		
    		if(flag)
    			cout << "YES
    ";
    		else
    			cout << "NO
    ";
    	
        	
    	}
        
         
        return 0;  
    } 
    
    /*
    1
    16 4
    ...AAAAA........
    s.BBB....CCCCC..
    .......DDDDD....
    */

    C - A Mist of Florescence

     题意,构造一个50*50 以内的矩阵,包含a个A联通快,b个B联通块,c个C联通块,d个D联通块。

    解法:构造4个25*25的ABCD矩阵连在一起, 然后每九宫格往里填即可。

    /*
    	    Zeolim - An AC a day keeps the bug away
    	*/
    	
    	//pragma GCC optimize(2)
    	#include <bits/stdc++.h>
    	typedef long long ll;
    	typedef long double ld;
    	typedef std::pair<int, int> pii;
    	//typedef __int128 ill;
    	const ld PI = acos(-1.0);
    	const ld E = exp(1.0);
    	const ll INF = 0x3f3f3f3f;
    	const ll MOD = 1e9 + 7;
    	using namespace std;
    	const int MAXN = 1e2 + 10;
    	
    	char mp[MAXN][MAXN] = {0};
    	
    	void init(int x, int y, char c)
    	{
    		for(int i = x; i < x + 25; ++i)
    		{
    			for(int j = y; j < y + 25; ++j)
    			{
    				mp[i][j] = c;
    			}
    		}
    	}
    	
    	void show()
    	{
    		for(int i = 0; i < 50; ++i)
    		{
    			for(int j = 0; j < 50; ++j)
    			{
    				cout << mp[i][j];
    			}
    			cout << '
    ';
    		}
    	}
    	
    	int main()  
    	{   
    		ios::sync_with_stdio(0);
    		cin.tie(0); cout.tie(0);  
    		
    		int a, b, c, d;
    		
    		cin >> a >> b >> c >> d;
    		
    		init(0, 0, 'A');
    		init(0, 25, 'B');
    		init(25, 0, 'C');
    		init(25, 25, 'D');
    		
    		--a, --b, --c, --d;
    		
    		for(int i = 1; i < 50; i += 2)
    		{
    			if(i == 25)
    				++i;
    			for(int j = 1; j < 50; j += 2)
    			{
    				if(j == 25)
    					++j;
    				if(a && mp[i][j] != 'A')
    				 	--a, mp[i][j] = 'A';
    				
    				else if(b && mp[i][j] != 'B')
    				 	--b, mp[i][j] = 'B';
    				
    				else if(c && mp[i][j] != 'C')
    					--c, mp[i][j] = 'C';
    				else if(d && mp[i][j] != 'D')
    					--d, mp[i][j] = 'D';
    			}
    		}
    		
    		
    		cout << "50 50
    ";
    		
    		show();
    		
    	    return 0;  
    	} 

    D - Unbearable Controversy of Being

    题意:求图中菱形个数

    遍历所有点能达到的长度为2的路径的到达点,map计数,加法原理记录答案。

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double ld;
    typedef std::pair<int, int> pii;
    #define mp(x, y) make_pair(x, y) 
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 1e18; 
    const ll MOD = 1e9 + 7;
    const int MAXN = 3e3 + 10;
    
    int n, m;
    
    vector <int> edge[MAXN];
    
    int ans = 0;
    
    map <int, int> rec;
    	
    bitset <MAXN> used[MAXN];
    
    
    
    void cal(int now)
    {
    	
    	rec.clear();
    	
    	for(int i = 1; i <= n; ++i)
    		used[i].reset();
    	
    	for(auto x : edge[now])
    	{
    		for(auto y : edge[x])
    		{
    			if(!used[x][y] && y != now)
    			{
    				ans += rec[y];
    				++rec[y];
    			}
    		}
    	}
    		
    	return ;
    }
    
    
    
    int main()
    { 	
    	cin >> n >> m;
    	
    	for(int i = 0, from, to; i < m; ++i)
    		cin >> from >> to, edge[from].push_back(to);
    		
    	for(int i = 1; i <= n; ++i)
    	{
    		cal(i);
    	}
    	
    	cout << ans << '
    ';
    	
        return 0;
    }

    E - Igor In the Museum

     题意:每个.和*之间都有一副画,求点x,y所在联通块内画的总数。

    思路:dfs染色记录答案输出

    我用的二维映射一维+并查集

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef std::pair<int, int> pii;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    const int MAXN = 2e6 + 10;
    
    char mp[1100][1100];
    bool used[1100][1100][4];
    
    int fa[MAXN] = {0};
    int val[MAXN] = {0};
    
    int movl[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
    
    int findfa(int x)
    {
    	return x == fa[x] ? x : fa[x] = findfa(fa[x]);
    }
    
    int n, m, k;
    
    int tra(int x, int y)
    {
    	return (x - 1) * m + y;
    }
    
    void oprt(int x, int y)
    {
    	for(int i = 0; i < 4; ++i)
    	{
    		int rx = x + movl[i][0], ry = y + movl[i][1], rp = tra(x, y);
    		if(mp[rx][ry] == '*' && !used[rx][ry][i])
    		{
    			++val[rp];
    			used[rx][ry][i] = true;
    		}
    	}
    	
    	for(int i = 0; i < 2; ++i)
    	{
    		int rx = x + movl[i][0], ry = y + movl[i][1], rp = tra(rx, ry), rrp = tra(x, y);
    		if(mp[rx][ry] == '.')
    		{
    			int p = findfa(rp), q = findfa(rrp);
    			if(p != q)
    			{
    				fa[p] = q;
    				val[q] += val[p];
    			}
    		}
    	}
    }
    
    int main()  
    {   
    	ios::sync_with_stdio(0);
    	cin.tie(0); cout.tie(0);  
    
        cin >> n >> m >> k;
        
        for(int i = 0; i <= n * m + n + m + 100; ++i)
        {
        	fa[i] = i;
    	}
        
        for(int i = 1; i <= n; ++i)
        {
        	for(int j = 1; j <= m; ++j)
        	{
        		cin >> mp[i][j];                    
    		}
    	}
    	
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= m; ++j)
    		{
    			if(mp[i][j] == '.')
    			{
    				oprt(i, j);
    			}
    		}
    	}
    	
    	
    	while(k--)
    	{
    		int x, y;
    		
    		cin >> x >> y;
    		
    		int rp = findfa( tra(x, y) );
    		
    		cout << val[rp] << '
    ';
    	}
        
        return 0;  
    } 

    F - The Child and Toy

     智障题,删每条边两端点最小点权之和

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef std::pair<int, int> pii;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    const int MAXN = 1e6 + 10;
    
    
    ll val[MAXN];
    
    int main()  
    {  
    	ios::sync_with_stdio(0);
    	cin.tie(0); cout.tie(0);
    	
    	int n, m;
    	
    	cin >> n >> m;
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		cin >> val[i];
    	}
    	
    	ll ans = 0;
    	
    	for(int i = 1; i <= m; ++i)
    	{
    		int p, q;
    		cin >> p >> q;
    		ans += min(val[p], val[q]);
    	}
    	
    	cout << ans << '
    ';
        
        return 0;  
    } 

    G - New Year Permutation

    一个矩阵,若i,j == j,i == 1则这部分有传递性可互换,求最小排列。

    用并查集维护联通块后set排序+位置直接复写数组输出即可

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double ld;
    typedef std::pair<int, int> pii;
    #define mp(x, y) make_pair(x, y) 
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 1e18; 
    const ll MOD = 1e9 + 7;
    const int MAXN = 5e2 + 10;
    
    int fa[MAXN];
    
    int findfa(int x)
    {
    	return x == fa[x] ? x : fa[x] = findfa(fa[x]);
    }
    
    int arr[MAXN] = {0};
    
    bitset <MAXN> ok[MAXN];
    
    set <int> ST[MAXN], RT[MAXN];
    
    int main()
    { 	
    	int n;
    	
    	cin >> n;
    	
    	for(int i = 1; i <= n; ++i)
    		cin >> arr[i];
    		
    	for(int i = 1; i <= n; ++i)
    	{
    		fa[i] = i;
    		for(int j = 1; j <= n; ++j)
    		{
    			char x;
    			
    			cin >> x;
    			
    			ok[i][j] = x == '1';
    		}
    	}
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= n; ++j)
    		{
    			if(ok[i][j] && ok[j][i])
    			{
    				int p = findfa(i), q = findfa(j);
    				
    				if(p != q)
    					fa[p] = q;
    			}
    		}
    	}
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		int p = findfa(i);
    		ST[p].insert(arr[i]);
    		RT[p].insert(i);
    	}
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		auto r = RT[i].begin();
    		for(auto x : ST[i])
    		{
    			arr[ *r ] = x;
    			++r;
    		}
    	}
    	
    	for(int i = 1; i <= n; ++i)
    		cout << arr[i] << ' ';
    	
    	
    	
    	
    	
        return 0;
    }

    H - Alyona and the Tree

     规定1为根节点,若存在dis(u,v) > val(u)则称u 伤心,问需要删多少点才让整棵树不伤心

    从根dfs统计不伤心的点,加上一点的树上dp (最大路径和)即可

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <bits/stdc++.h>
    typedef long long ll;
    typedef long double ld;
    typedef std::pair<int, int> pii;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    const int MAXN = 1e6 + 10;
    
    ll val[MAXN] = {0};
    bool used[MAXN] = {0};
    
    struct node
    {
    	ll to, val;
    	node(){}
    	node(int x, int y)
    	{
    		to = x;
    		val = y;
    	} 
    };
    
    vector <node> edge[MAXN];
    
    
    int n, k;
    
    void dfs(ll now, ll sum)
    {
    	if(sum > val[now])
    		return;
    		
    	used[now] = true;
    	
    	for(int i = 0; i < edge[now].size(); ++i)
    	{
    		if(!used[edge[now][i].to])
    			dfs(edge[now][i].to, max(sum + edge[now][i].val, edge[now][i].val));
    	}
    }
    
    
    int main()  
    {   
        cin >> n;
        
        for(int i = 1; i <= n; ++i)
        	cin >> val[i];
        	
        for(int i = 2; i <= n; ++i)
        {
        	int to, val;
        	cin >> to >> val;
        	edge[i].push_back(node(to, val));
        	edge[to].push_back(node(i, val));
    	}
    	
    	dfs(1, 0);
    	
    	int ans = n;
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		if(used[i])
    			--ans;
    	}
    	
    	cout << ans << '
    ';
    	
        return 0;  
    } 
  • 相关阅读:
    C#-WebApi-EF-CodeFirst-构建迁移命令说明
    webform-rdlc报表报错:未能加载文件或程序集Microsoft.SqlServer.Types版本错误的处理方案
    Observable与Subject
    使用ionic生成apk时遇到的错误:[ERROR] An error occurred while running subprocess cordova
    Socket通讯
    Transactions-事务
    Visual studio2017前端项目包管理从Borwer升级到libman
    NetCore-EFCore-DBfirst-同步数据库生成Model
    学习计划
    关于Vue2.5 less 版本过高
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270358.html
Copyright © 2020-2023  润新知