图论练习3

内容:过程中视条件改变边权,利用树状数组区间加处理


卯酉东海道

题目链接

题目大意

  • 个点,条有向边,每条边有颜色和费用
  • 总共有种颜色
  • 若当前颜色与要走的边颜色相同,则花费为
  • 若当前颜色与要走的边颜色不同,则花费为,且颜色变为边的颜色
  • 出发时可以自定义颜色
  • 的最小花费

解题思路

  • 选边时,进行判断
  • 对于初始自定义颜色,且,则跑趟最短路
java 复制代码
import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.StringTokenizer;


 public class Main{
	static
	class Node{
		int id;
		int col;
		long dis;
		public Node(int I,int C,long D) {
			id=I;
			col=C;
			dis=D;
		}
	}
	static int cnt=0;
	static int[] head;
	static Edge[] e;
	static
	class Edge{
		int fr;
		int to;
		int nxt;
		long val;
		int col;
	}
	static void addEdge(int fr,int to,long val,int col) {
		cnt++;
		e[cnt]=new Edge();
		e[cnt].fr=fr;
		e[cnt].to=to;
		e[cnt].val=val;
		e[cnt].nxt=head[fr];
		e[cnt].col=col;
		head[fr]=cnt;
	}
	public static void main(String[] args) throws IOException{
		
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    int m=input.nextInt();
	    int l=input.nextInt();
	    int base=input.nextInt();
	    e=new Edge[m<<1|1];
	    head=new int[n+1];
	    for(int i=1;i<=m;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	int col=input.nextInt();
	    	long w=input.nextLong();
	    	addEdge(u, v, w,col);	
	    }
	    PriorityQueue<Node> que=new PriorityQueue<Node>((o1,o2)->{
	    		if(o1.dis-o2.dis>0)return 1;
	    		else if(o1.dis-o2.dis<0)return -1;
	    		else return 0;
	    });
	    boolean[] vis=new boolean[n+1];
	    long[] dis=new long[n+1];
	    long ans=Long.MAX_VALUE;
	    for(int o=1;o<=l;++o) {
	    	Node s=new Node(1,o,0);
	    	Arrays.fill(vis, false);
	    	Arrays.fill(dis, Long.MAX_VALUE);
	    	dis[1]=0;
	    	que.add(s);
	    	while(!que.isEmpty()) {
	    		Node now=que.peek();
                que.poll();
	    		int u=now.id;
                if(vis[u])continue;
	    		long disu=now.dis;
	    		int colu=now.col;
	    		vis[u]=true;
	    		for(int i=head[u];i>0;i=e[i].nxt) {
	    			int v=e[i].to;
	    			int colv=e[i].col;
	    			long w=e[i].val;

	    			if(colv!=colu) {
                        w=base*w;
                    }
	    			if(dis[v]>disu+w) {
	    				dis[v]=disu+w;
	    				que.add(new Node(v, colv, dis[v]));
	    			}
	   
	    		}
	    	}
	    	ans=Math.min(ans, dis[n]);
	    }
	    if(ans==Long.MAX_VALUE) {
	    	out.println(-1);
	    }else {
	    	out.println(ans);
	    }
		out.flush();
		out.close();
	}
	
	static
	class AReader{
	    BufferedReader bf;
	    StringTokenizer st;
	    BufferedWriter bw;
 
	    public AReader(){
	        bf=new BufferedReader(new InputStreamReader(System.in));
	        st=new StringTokenizer("");
	        bw=new BufferedWriter(new OutputStreamWriter(System.out));
	    }
	    public String nextLine() throws IOException{
	        return bf.readLine();
	    }
	    public String next() throws IOException{
	        while(!st.hasMoreTokens()){
	            st=new StringTokenizer(bf.readLine());
	        }
	        return st.nextToken();
	    }
	    public char nextChar() throws IOException{
	        //确定下一个token只有一个字符的时候再用
	        return next().charAt(0);
	    }
	    public int nextInt() throws IOException{
	        return Integer.parseInt(next());
	    }
	    public long nextLong() throws IOException{
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException{
	        return Double.parseDouble(next());
	    }
	    public float nextFloat() throws IOException{
	        return Float.parseFloat(next());
	    }
	    public byte nextByte() throws IOException{
	        return Byte.parseByte(next());
	    }
	    public short nextShort() throws IOException{
	        return Short.parseShort(next());
	    }
	    public BigInteger nextBigInteger() throws IOException{
	        return new BigInteger(next());
	    }
	    public void println() throws IOException {
	        bw.newLine();
	    }
	    public void println(int[] arr) throws IOException{
	        for (int value : arr) {
	            bw.write(value + " ");
	        }
	        println();
	    }
	    public void println(int l, int r, int[] arr) throws IOException{
	        for (int i = l; i <= r; i ++) {
	            bw.write(arr[i] + " ");
	        }
	        println();
	    }
	    public void println(int a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(int a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(String a) throws IOException{
	        bw.write(a);
	        bw.newLine();
	    }
	    public void print(String a) throws IOException{
	        bw.write(a);
	    }
	    public void println(long a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(long a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(double a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	    public void print(double a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void print(char a) throws IOException{
	        bw.write(String.valueOf(a));
	    }
	    public void println(char a) throws IOException{
	        bw.write(String.valueOf(a));
	        bw.newLine();
	    }
	}
}

AtCoder abc338 D - Island Tour

题目链接

题目大意

  • 个点,条无向边依次连接,第条连接
  • 给定序列,从依次访问
  • 的路径长度,定义为经过的边的个数
  • 问删除一条边后,完成访问的最短路径长度

解题思路

  • 先不管删边
  • 有两种方式,一种绕一圈,一种直接顺着走
  • 两种方式种的较小值加入答案
  • 但是有删边,所以删去边后可能导致取到较小值的路径无法通过,需要撤回,改为另一种
  • 若删除这条边,则通过它的所有较小值均要改变,即加上差值
  • 由于边标号连续,考虑树状数组区间加
  • 对于当前较小值经过的所有边,加上差值,作为撤回代价
  • 在不考虑删边的情况下统计完答案后,单点查询每条边,取撤回代价最小的边为删边
java 复制代码
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.StringTokenizer;




public class Main{
	static int cnt=0;
	static int[] head;
	static
	class Edge{
		int fr;
		int to;
		int nxt;
		long val;
	}
	static Edge[] e;
	static void addEdge(int fr,int to,long val) {
		cnt++;
		e[cnt]=new Edge();
		e[cnt].fr=fr;
		e[cnt].to=to;
		e[cnt].nxt=head[fr];
		head[fr]=cnt;
	}
	static
	class Node{
		int x;
		long dis;
		long h;
		public Node(int X,long D,long H) {
			x=X;
			dis=D;
			h=H;
		}
	}
	static
	class BIT{
		int size;
		long[] tr;
		public BIT(int n) {
			size=n;
			tr=new long[n+2];
		}
		public int lowbit(int x) {
			return x&(-x);
		}
		public void update(int x,long y) {
			for(int i=x;i<=size;i+=lowbit(i)) {
				tr[i]+=y;
			}
		}
		public long query(int x) {
			long res=0;
			for(int i=x;i>0;i-=lowbit(i)) {
				res+=tr[i];
			}
			return res;
		}
	}
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    int m=input.nextInt();
	    BIT Tree=new BIT(n);
	    int[] X=new int[m+1];
	    for(int i=1;i<=m;++i) {
	    	X[i]=input.nextInt();
	    }
	    long ans=0;
	    for(int i=1;i<m;++i) {
	    	int x=X[i];
	    	int y=X[i+1];
	    	if(x==y)continue;
	    	long tol;
	    	long tor;
	    	long cha;
	    	if(x<y) {
	    		tol=(n+x-y);
	    		tor=(y-x);
	    		
	    		if(tol>tor) {
	    			ans+=tor;
	    			cha=tol-tor;
	    			Tree.update(x, cha);
	    			Tree.update(y, -cha);
	    		}else {
	    			ans+=tol;
	    			cha=tor-tol;
	    			
	    			Tree.update(1, cha);
	    			Tree.update(x,-cha);
	    			Tree.update(y, cha);
	    			Tree.update(n+1, -cha);
	    		}
	    	}else {
	    		tol=x-y;
	    		tor=n-x+y;
	    		if(tol>tor) {
	    			ans+=tor;
	    			cha=tol-tor;
	    			Tree.update(x, cha);
	    			Tree.update(n+1,-cha);
	    			Tree.update(1, cha);
	    			Tree.update(y, -cha);
	    		}else {
	    			ans+=tol;
	    			cha=tor-tol;
	    			Tree.update(y, cha);
	    			Tree.update(x, -cha);
	    		}
	    	}
	    }
	    long shan=Long.MAX_VALUE/2;
	    
	    for(int i=1;i<=n;++i) {
	    	shan=Math.min(shan, Tree.query(i));
	    }
//	    out.println(ans);
	    out.println(ans+shan);
 	    out.flush();
	    out.close();
	}
	
	static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
 
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}

AtCoder abc338 E - Chords

题目链接

题目大意

  • 在一个圆上等距离放置了个点,从某个点开始顺时针编号为
  • 同时在圆上有条弦,第i条弦连接点。保证所有的不同
  • 判断这些弦是否有交

解题思路

  • 集合划分
  • 若两个不同集合之间有弦,则有交
  • 由于点标号连续,对于每个弦,考虑树状数组区间加
  • 之间的点,区间加,表示一个新集合
  • 端点无所谓,反正保证所有的不同
  • ,则不在一个集合且有弦,满足有交
java 复制代码
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.StringTokenizer;




public class Main{
	static int cnt=0;
	static int[] head;
	static
	class Edge{
		int fr;
		int to;
		int nxt;
		long val;
	}
	static Edge[] e;
	static void addEdge(int fr,int to,long val) {
		cnt++;
		e[cnt]=new Edge();
		e[cnt].fr=fr;
		e[cnt].to=to;
		e[cnt].nxt=head[fr];
		head[fr]=cnt;
	}
	static
	class Node{
		int x;
		long dis;
		long h;
		public Node(int X,long D,long H) {
			x=X;
			dis=D;
			h=H;
		}
	}
	static
	class BIT{
		int size;
		long[] tr;
		public BIT(int n) {
			size=n;
			tr=new long[n+2];
		}
		public int lowbit(int x) {
			return x&(-x);
		}
		public void update(int x,long y) {
			for(int i=x;i<=size;i+=lowbit(i)) {
				tr[i]+=y;
			}
		}
		public long query(int x) {
			long res=0;
			for(int i=x;i>0;i-=lowbit(i)) {
				res+=tr[i];
			}
			return res;
		}
	}
	public static void main(String[] args) throws IOException{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	    int n=input.nextInt();
	    BIT Tree=new BIT(2*n);
	    boolean ok=true;
	    
	    for(int i=1;i<=n;++i) {
	    	int x=input.nextInt();
	    	int y=input.nextInt();
	    	if(x>y) {
	    		int t=x;
	    		x=y;
	    		y=t;
	    	}
	    	if(!ok)continue;
	    	long fx=Tree.query(x);
	    	long fy=Tree.query(y);
	    	if(fx!=fy) {
	    		ok=false;
	    	}else {
	    		Tree.update(x, 1);
	    		Tree.update(y, -1);
	    	}
	    }
	    if(ok) {
	    	out.println("No");
	    }else {
	    	out.println("Yes");
	    }
 	    out.flush();
	    out.close();
	}
	
	static
    class AReader {
        private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        private StringTokenizer tokenizer = new StringTokenizer("");
        private String innerNextLine() {
            try {
                return reader.readLine();
            } catch (IOException ex) {
                return null;
            }
        }
        public boolean hasNext() {
            while (!tokenizer.hasMoreTokens()) {
                String nextLine = innerNextLine();
                if (nextLine == null) {
                    return false;
                }
                tokenizer = new StringTokenizer(nextLine);
            }
            return true;
        }
        public String nextLine() {
            tokenizer = new StringTokenizer("");
            return innerNextLine();
        }
        public String next() {
            hasNext();
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
 
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
        	return Double.parseDouble(next());
        }
    }
}
相关推荐
hn小菜鸡32 分钟前
LeetCode 面试经典150题 67.二进制求和
算法·leetcode·面试
还听珊瑚海吗1 小时前
数据结构——二叉树
数据结构·算法
小灰灰爱代码1 小时前
C++——求3*3矩阵主对角元素之和。
c++·算法·矩阵
鱼跃鹰飞2 小时前
Leetcode面试经典150题-94.二叉树的中序遍历
算法·leetcode·面试
Roam-G2 小时前
Java 中常用的排序算法
数据结构·算法·排序算法
hjxxlsx2 小时前
插入与冒泡排序(C++)
c++·算法·排序算法
Skrrapper2 小时前
【数据结构】排序算法系列——快速排序(附源码+图解)
c语言·数据结构·算法·排序算法
Mephisto.java2 小时前
【力扣 | SQL题 | 每日三题】力扣175, 176, 181
sql·算法·leetcode
木向2 小时前
leetcode第十二题:整数转罗马数字
c++·算法·leetcode·职场和发展
繁星璀璨G2 小时前
C++11标准模板(STL)- 常用数学函数 - 计算e的给定幂 (ex)(std::exp, std::expf, std::expl)
开发语言·c++·算法·stl·计算e的给定幂